Merge branch 'master' into httptests

httptests
UbitUmarov 2016-12-25 05:51:08 +00:00
commit 1b95ada105
8 changed files with 156 additions and 55 deletions

View File

@ -135,6 +135,7 @@ namespace OpenSim.Framework
public string born; public string born;
public byte[] membershipType; public byte[] membershipType;
public uint flags; public uint flags;
public HashSet<IClientAPI> ClientsWaitingProps;
} }
} }

View File

@ -1725,12 +1725,16 @@ namespace OpenSim.Framework
return new UUID(bytes, 0); return new UUID(bytes, 0);
} }
public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y) public static bool ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y)
{ {
byte[] bytes = parcelID.GetBytes(); byte[] bytes = parcelID.GetBytes();
regionHandle = Utils.BytesToUInt64(bytes); regionHandle = Utils.BytesToUInt64(bytes);
x = Utils.BytesToUInt(bytes, 8) & 0xffff; x = Utils.BytesToUInt(bytes, 8) & 0xffff;
y = Utils.BytesToUInt(bytes, 12) & 0xffff; y = Utils.BytesToUInt(bytes, 12) & 0xffff;
// validation may fail, just reducing the odds of using a real UUID as encoded parcel
return ( bytes[0] == 0 && bytes[4] == 0 && // handler x,y multiples of 256
bytes[9] < 64 && bytes[13] < 64 && // positions < 16km
bytes[14] == 0 && bytes[15] == 0);
} }
public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z) public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z)

View File

@ -62,7 +62,8 @@ namespace OpenSim.Region.CoreModules.Asset
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Enabled; private bool m_Enabled;
private bool m_Running; private bool m_timerRunning;
private bool m_cleanupRunning;
private const string m_ModuleName = "FlotsamAssetCache"; private const string m_ModuleName = "FlotsamAssetCache";
private const string m_DefaultCacheDirectory = "./assetcache"; private const string m_DefaultCacheDirectory = "./assetcache";
@ -91,9 +92,8 @@ namespace OpenSim.Region.CoreModules.Asset
private bool m_MemoryCacheEnabled = false; private bool m_MemoryCacheEnabled = false;
// Expiration is expressed in hours. // Expiration is expressed in hours.
private const double m_DefaultMemoryExpiration = 2; private double m_MemoryExpiration = 0.001;
private const double m_DefaultFileExpiration = 48; private const double m_DefaultFileExpiration = 48;
private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration);
private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0);
@ -150,7 +150,8 @@ namespace OpenSim.Region.CoreModules.Asset
m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration);
m_MemoryExpiration *= 3600.0; // config in hours to seconds
#if WAIT_ON_INPROGRESS_REQUESTS #if WAIT_ON_INPROGRESS_REQUESTS
m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000);
@ -224,9 +225,9 @@ namespace OpenSim.Region.CoreModules.Asset
m_Scenes.Remove(scene); m_Scenes.Remove(scene);
lock(timerLock) lock(timerLock)
{ {
if(m_Running && m_Scenes.Count <= 0) if(m_timerRunning && m_Scenes.Count <= 0)
{ {
m_Running = false; m_timerRunning = false;
m_CacheCleanTimer.Stop(); m_CacheCleanTimer.Stop();
m_CacheCleanTimer.Close(); m_CacheCleanTimer.Close();
} }
@ -242,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Asset
m_AssetService = scene.RequestModuleInterface<IAssetService>(); m_AssetService = scene.RequestModuleInterface<IAssetService>();
lock(timerLock) lock(timerLock)
{ {
if(!m_Running) if(!m_timerRunning)
{ {
if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
{ {
@ -250,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Asset
m_CacheCleanTimer.AutoReset = false; m_CacheCleanTimer.AutoReset = false;
m_CacheCleanTimer.Elapsed += CleanupExpiredFiles; m_CacheCleanTimer.Elapsed += CleanupExpiredFiles;
m_CacheCleanTimer.Start(); m_CacheCleanTimer.Start();
m_Running = true; m_timerRunning = true;
} }
} }
} }
@ -263,6 +264,7 @@ namespace OpenSim.Region.CoreModules.Asset
private void UpdateMemoryCache(string key, AssetBase asset) private void UpdateMemoryCache(string key, AssetBase asset)
{ {
// NOTE DO NOT USE SLIDEEXPIRE option on current libomv
m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration);
} }
@ -480,12 +482,10 @@ namespace OpenSim.Region.CoreModules.Asset
asset = GetFromMemoryCache(id); asset = GetFromMemoryCache(id);
if (asset == null && m_FileCacheEnabled) if (asset == null && m_FileCacheEnabled)
{
asset = GetFromFileCache(id); asset = GetFromFileCache(id);
if (m_MemoryCacheEnabled && asset != null) if (m_MemoryCacheEnabled && asset != null)
UpdateMemoryCache(id, asset); UpdateMemoryCache(id, asset);
}
if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
{ {
@ -561,8 +561,12 @@ namespace OpenSim.Region.CoreModules.Asset
if (m_LogLevel >= 2) if (m_LogLevel >= 2)
m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration); m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration);
if(!m_Running) lock(timerLock)
return; {
if(!m_timerRunning || m_cleanupRunning)
return;
m_cleanupRunning = true;
}
// Purge all files last accessed prior to this point // Purge all files last accessed prior to this point
DateTime purgeLine = DateTime.Now - m_FileExpiration; DateTime purgeLine = DateTime.Now - m_FileExpiration;
@ -578,8 +582,9 @@ namespace OpenSim.Region.CoreModules.Asset
lock(timerLock) lock(timerLock)
{ {
if(m_Running) if(m_timerRunning)
m_CacheCleanTimer.Start(); m_CacheCleanTimer.Start();
m_cleanupRunning = false;
} }
} }
@ -816,13 +821,13 @@ namespace OpenSim.Region.CoreModules.Asset
s.ForEachSOG(delegate(SceneObjectGroup e) s.ForEachSOG(delegate(SceneObjectGroup e)
{ {
if(!m_Running && !storeUncached) if(!m_timerRunning && !storeUncached)
return; return;
gatherer.AddForInspection(e); gatherer.AddForInspection(e);
gatherer.GatherAll(); gatherer.GatherAll();
if(!m_Running && !storeUncached) if(!m_timerRunning && !storeUncached)
return; return;
foreach (UUID assetID in gatherer.GatheredUuids.Keys) foreach (UUID assetID in gatherer.GatheredUuids.Keys)
@ -854,13 +859,13 @@ namespace OpenSim.Region.CoreModules.Asset
} }
gatherer.GatheredUuids.Clear(); gatherer.GatheredUuids.Clear();
if(!m_Running && !storeUncached) if(!m_timerRunning && !storeUncached)
return; return;
if(!storeUncached) if(!storeUncached)
Thread.Sleep(50); Thread.Sleep(50);
}); });
if(!m_Running && !storeUncached) if(!m_timerRunning && !storeUncached)
break; break;
} }
@ -905,16 +910,23 @@ namespace OpenSim.Region.CoreModules.Asset
{ {
List<string> outputLines = new List<string>(); List<string> outputLines = new List<string>();
double fileHitRate = (double)m_DiskHits / m_Requests * 100.0; double invReq = 100.0 / m_Requests;
double fileHitRate = m_DiskHits * invReq;
outputLines.Add( outputLines.Add(
string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests)); string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
if (m_MemoryCacheEnabled) if (m_MemoryCacheEnabled)
{ {
double memHitRate = (double)m_MemoryHits / m_Requests * 100.0; double HitRate = m_MemoryHits * invReq;
outputLines.Add( outputLines.Add(
string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests)); string.Format("Memory Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests));
HitRate += fileHitRate;
outputLines.Add(
string.Format("Total Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests));
} }
outputLines.Add( outputLines.Add(
@ -1019,17 +1031,27 @@ namespace OpenSim.Region.CoreModules.Asset
break; break;
case "assets": case "assets":
con.Output("Ensuring assets are cached for all scenes."); lock(timerLock)
{
if(m_cleanupRunning)
{
con.OutputFormat("FloatSam assets check already running");
return;
}
m_cleanupRunning = true;
}
con.Output("FloatSam Ensuring assets are cached for all scenes.");
WorkManager.RunInThread(delegate WorkManager.RunInThread(delegate
{ {
bool wasRunning= false; bool wasRunning= false;
lock(timerLock) lock(timerLock)
{ {
if(m_Running) if(m_timerRunning)
{ {
m_CacheCleanTimer.Stop(); m_CacheCleanTimer.Stop();
m_Running = false; m_timerRunning = false;
wasRunning = true; wasRunning = true;
Thread.Sleep(100); Thread.Sleep(100);
} }
@ -1041,8 +1063,9 @@ namespace OpenSim.Region.CoreModules.Asset
if(wasRunning) if(wasRunning)
{ {
m_CacheCleanTimer.Start(); m_CacheCleanTimer.Start();
m_Running = true; m_timerRunning = true;
} }
m_cleanupRunning = false;
} }
con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal); con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
}, null, "TouchAllSceneAssets"); }, null, "TouchAllSceneAssets");

View File

@ -897,20 +897,36 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
else else
{ {
// we have a proxy on map // we have a proxy on map
// this is a fail on large regions ulong oriHandle;
uint gtmp = (uint)globalPos.X >> 8; uint oriX;
globalPos.X -= (gtmp << 8); uint oriY;
globalPos.X += target.RegionLocX; if(Util.ParseFakeParcelID(pick.ParcelId, out oriHandle, out oriX, out oriY))
{
pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, oriX, oriY);
globalPos.X = target.RegionLocX + oriX;
globalPos.Y = target.RegionLocY + oriY;
pick.GlobalPos = globalPos.ToString();
}
else
{
// this is a fail on large regions
uint gtmp = (uint)globalPos.X >> 8;
globalPos.X -= (gtmp << 8);
gtmp = (uint)globalPos.Y >> 8; gtmp = (uint)globalPos.Y >> 8;
globalPos.Y -= (gtmp << 8); globalPos.Y -= (gtmp << 8);
globalPos.Y += target.RegionLocY;
pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, (uint)globalPos.X, (uint)globalPos.Y);
globalPos.X += target.RegionLocX;
globalPos.Y += target.RegionLocY;
pick.GlobalPos = globalPos.ToString();
}
} }
} }
m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
pick.GlobalPos = globalPos.ToString();
lock(m_profilesCache) lock(m_profilesCache)
{ {
if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null) if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null)
@ -1331,16 +1347,35 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
if(uce.props != null) if(uce.props != null)
{ {
props = uce.props; props = uce.props;
remoteClient.SendAvatarProperties(props.UserId, props.AboutText, uint cflags = uce.flags;
uce.born, uce.membershipType , props.FirstLifeText, uce.flags, // if on same region force online
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); if(p != null && !p.IsDeleted)
cflags |= 0x10;
remoteClient.SendAvatarProperties(props.UserId, props.AboutText,
uce.born, uce.membershipType , props.FirstLifeText, cflags,
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask,
props.WantToText, (uint)props.SkillsMask, props.WantToText, (uint)props.SkillsMask,
props.SkillsText, props.Language); props.SkillsText, props.Language);
return; return;
} }
else
{
if(uce.ClientsWaitingProps == null)
uce.ClientsWaitingProps = new HashSet<IClientAPI>();
else if(uce.ClientsWaitingProps.Contains(remoteClient))
return;
uce.ClientsWaitingProps.Add(remoteClient);
}
}
else
{
uce = new UserProfileCacheEntry();
uce.ClientsWaitingProps = new HashSet<IClientAPI>();
uce.ClientsWaitingProps.Add(remoteClient);
m_profilesCache.AddOrUpdate(avatarID, uce, PROFILECACHEEXPIRE);
} }
} }
@ -1402,14 +1437,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
{ {
props.AboutText ="Profile not available at this time. User may still be unknown to this grid"; props.AboutText ="Profile not available at this time. User may still be unknown to this grid";
} }
// if on same region force online
if(p != null && !p.IsDeleted)
flags |= 0x10;
if(!m_allowUserProfileWebURLs) if(!m_allowUserProfileWebURLs)
props.WebUrl =""; props.WebUrl ="";
HashSet<IClientAPI> clients;
lock(m_profilesCache) lock(m_profilesCache)
{ {
if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null) if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null)
@ -1418,15 +1450,39 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
uce.born = born; uce.born = born;
uce.membershipType = membershipType; uce.membershipType = membershipType;
uce.flags = flags; uce.flags = flags;
clients = uce.ClientsWaitingProps;
uce.ClientsWaitingProps = null;
m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE); m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
} }
remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, // if on same region force online
if(p != null && !p.IsDeleted)
flags |= 0x10;
if(clients == null)
{
remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
props.SkillsText, props.Language); (uint)props.SkillsMask, props.SkillsText, props.Language);
}
else
{
if(!clients.Contains(remoteClient))
clients.Add(remoteClient);
foreach(IClientAPI cli in clients)
{
if(!cli.IsActive)
continue;
cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
(uint)props.SkillsMask, props.SkillsText, props.Language);
}
}
} }
/// <summary> /// <summary>

View File

@ -1880,8 +1880,9 @@ namespace OpenSim.Region.CoreModules.World.Land
UUID.TryParse(id, out parcel); UUID.TryParse(id, out parcel);
// assume we've got the parcelID we just computed in RemoteParcelRequest // assume we've got the parcelID we just computed in RemoteParcelRequest
ExtendedLandData extLandData = new ExtendedLandData(); ExtendedLandData extLandData = new ExtendedLandData();
Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, if(!Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle,
out extLandData.X, out extLandData.Y); out extLandData.X, out extLandData.Y))
return null;
m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
extLandData.RegionHandle, extLandData.X, extLandData.Y); extLandData.RegionHandle, extLandData.X, extLandData.Y);

View File

@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
foreach (string id in ids) foreach (string id in ids)
{ {
string current = id.Trim(); string current = id.Trim();
if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GRID_GOD") if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GOD" || current.ToUpper() == "GRID_GOD")
{ {
if (!perms.AllowedOwnerClasses.Contains(current)) if (!perms.AllowedOwnerClasses.Contains(current))
perms.AllowedOwnerClasses.Add(current.ToUpper()); perms.AllowedOwnerClasses.Add(current.ToUpper());
@ -416,9 +416,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
//Only gods may use the function //Only gods may use the function
if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GOD"))
{
if (World.Permissions.IsGod(ownerID))
{
return String.Empty;
}
}
//Only grid gods may use the function
if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GRID_GOD")) if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GRID_GOD"))
{ {
if (World.Permissions.IsGridGod(ownerID)) if (World.Permissions.IsGridGod(ownerID))
{ {
return String.Empty; return String.Empty;
} }

View File

@ -20,15 +20,20 @@
HitRateDisplay = 100 HitRateDisplay = 100
; Set to false for no memory cache ; Set to false for no memory cache
MemoryCacheEnabled = false ; assets can be requested several times in short periods
; so even a small memory cache is usefull
MemoryCacheEnabled = true
; Set to false for no file cache ; Set to false for no file cache
FileCacheEnabled = true FileCacheEnabled = true
; How long {in hours} to keep assets cached in memory, .5 == 30 minutes ; How long {in hours} to keep assets cached in memory, .5 == 30 minutes
; Optimization: for VPS or limited memory system installs set Timeout to .016 (1 minute) ; even a few minutes may mean many assets loaded to memory, if not all.
; increases performance without large memory impact ; this is good if memory is not a problem.
MemoryCacheTimeout = 2 ; if memory is a problem then a few seconds may actually save same.
; reducing duplications.
; see hit rates with console comand: fcache status
MemoryCacheTimeout = .001 // 3.6s ie around 4s (1s resolution)
; How long {in hours} to keep assets cached on disk, .5 == 30 minutes ; How long {in hours} to keep assets cached on disk, .5 == 30 minutes
; Specify 0 if you do not want your disk cache to expire ; Specify 0 if you do not want your disk cache to expire

View File

@ -37,6 +37,8 @@
; To enable for individuals or groups, set it to a comma separated list. This checks ; To enable for individuals or groups, set it to a comma separated list. This checks
; against the owner of the object containing the script. ; against the owner of the object containing the script.
; The comma separated entries in the list may be one of: ; The comma separated entries in the list may be one of:
; "GRID_GOD" -- enable for users with UserLevel >= 200
; "GOD" -- enable for users with any type of god rights
; "ESTATE_MANAGER" -- enable for estate manager ; "ESTATE_MANAGER" -- enable for estate manager
; "ESTATE_OWNER" -- enable for estate owner ; "ESTATE_OWNER" -- enable for estate owner
; "PARCEL_OWNER" -- enable for parcel owner ; "PARCEL_OWNER" -- enable for parcel owner