Merge branch 'opensim:master' into master

This commit is contained in:
AdilElFarissi
2024-04-08 07:17:51 +00:00
committed by GitHub
57 changed files with 643 additions and 421 deletions

View File

@@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Framework
@@ -127,20 +128,19 @@ namespace OpenSim.Framework
Console.WriteLine("--------------------");
}
public static readonly byte[] ZeroCountBytesReply = osUTF8.GetASCIIBytes("version 1\ncount 0\n");
public Byte[] ToBytes()
{
// If there was an error parsing the input, we give back an
// empty set rather than the original data.
if (m_parseError)
{
string dummy = "version 1\ncount 0\n";
return System.Text.Encoding.ASCII.GetBytes(dummy);
}
if (m_parseError || m_animations.Count == 0)
return ZeroCountBytesReply;
string assetData = String.Format("version 1\ncount {0}\n", m_animations.Count);
osUTF8 sb = OSUTF8Cached.Acquire();
sb.AppendASCII("$version 1\ncount {m_animations.Count}\n");
foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key);
return System.Text.Encoding.ASCII.GetBytes(assetData);
sb.AppendASCII($"{kvp.Key} {kvp.Value.Value} {kvp.Value.Key}\n");
return OSUTF8Cached.GetArrayAndRelease(sb);
}
/*
public bool Validate(AnimationSetValidator val)

View File

@@ -32,6 +32,7 @@ using OpenMetaverse;
using OpenMetaverse.StructuredData;
using log4net;
using System.Text;
using System.Runtime.InteropServices;
namespace OpenSim.Framework
{
@@ -541,16 +542,20 @@ namespace OpenSim.Framework
lock (m_attachments)
{
if (!m_attachments.ContainsKey(attach.AttachPoint))
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
ref List<AvatarAttachment> atlst = ref CollectionsMarshal.GetValueRefOrAddDefault(m_attachments, attach.AttachPoint, out bool ex);
if(!ex)
{
atlst = new List<AvatarAttachment>() { attach };
return;
}
foreach (AvatarAttachment prev in m_attachments[attach.AttachPoint])
foreach (AvatarAttachment prev in atlst)
{
if (prev.ItemID.Equals(attach.ItemID))
return;
}
m_attachments[attach.AttachPoint].Add(attach);
atlst.Add(attach);
}
}
@@ -562,8 +567,7 @@ namespace OpenSim.Framework
lock (m_attachments)
{
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
m_attachments[attach.AttachPoint].Add(attach);
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>() { attach };
}
}

View File

@@ -185,11 +185,8 @@ namespace OpenSim.Framework
public void RemoveItem(UUID itemID)
{
if (m_items.ContainsKey(itemID))
{
m_ids.Remove(itemID);
m_items.Remove(itemID);
}
m_ids.Remove(itemID);
m_items.Remove(itemID);
}
public void RemoveAsset(UUID assetID)
@@ -225,9 +222,7 @@ namespace OpenSim.Framework
public UUID GetAsset(UUID itemID)
{
if (!m_items.ContainsKey(itemID))
return UUID.Zero;
return m_items[itemID];
return m_items.TryGetValue(itemID, out UUID id) ? id : UUID.Zero;
}
public static AvatarWearable[] DefaultWearables

View File

@@ -103,7 +103,7 @@ namespace OpenSim.Framework
public bool IsBlocked(string key)
{
bool ret = false;
_blockLockSlim.EnterReadLock();
_blockLockSlim.EnterReadLock();
ret = _tempBlocked.ContainsKey(key);
_blockLockSlim.ExitReadLock();
return ret;
@@ -140,11 +140,8 @@ namespace OpenSim.Framework
if (_options.MaxConcurrentSessions > 0)
{
int sessionscount = 0;
_sessionLockSlim.EnterReadLock();
if (_sessions.ContainsKey(key))
sessionscount = _sessions[key];
_sessions.TryGetValue(key, out int sessionscount);
_sessionLockSlim.ExitReadLock();
if (sessionscount > _options.MaxConcurrentSessions)

View File

@@ -344,26 +344,20 @@ namespace OpenSim.Framework
//
protected virtual CacheItemBase GetItem(string index)
{
CacheItemBase item = null;
lock (m_Index)
{
if (m_Lookup.ContainsKey(index))
item = m_Lookup[index];
if (item == null)
if(m_Lookup.TryGetValue(index, out CacheItemBase item))
{
item.hits++;
item.lastUsed = DateTime.UtcNow;
Expire(true);
return null;
return item;
}
item.hits++;
item.lastUsed = DateTime.UtcNow;
Expire(true);
return null;
}
return item;
}
// Get an item from cache. Do not try to fetch from source if not
@@ -566,12 +560,9 @@ namespace OpenSim.Framework
{
lock (m_Index)
{
if (!m_Lookup.ContainsKey(uuid))
return;
CacheItemBase item = m_Lookup[uuid];
if (m_Lookup.TryGetValue(uuid, out CacheItemBase item))
m_Index.Remove(item);
m_Lookup.Remove(uuid);
m_Index.Remove(item);
}
}

View File

@@ -46,39 +46,36 @@ namespace OpenSim.Framework.Monitoring
public virtual string Report()
{
StringBuilder sb = new StringBuilder(Environment.NewLine);
sb.Append("MEMORY STATISTICS");
sb.Append(Environment.NewLine);
sb.AppendFormat(
"Heap allocated to OpenSim : {0} MB\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
sb.AppendFormat(
"Heap allocation rate (last/avg): {0}/{1}MB/s\n",
"Heap allocated: {0}MB \t allocation rate (last/avg): {1}/{2}MB/s\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0),
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1048576.0, 3),
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1048576.0, 3));
GCMemoryInfo gcmem = GC.GetGCMemoryInfo();
sb.AppendFormat(
"GCTotalCommited: {0}MB \t GCTotalAvaiable {1}MB \t GCHMthreshold {2}MB\n",
Math.Round(gcmem.TotalCommittedBytes / 1024.0 / 1024.0),
Math.Round(gcmem.TotalAvailableMemoryBytes / 1024.0 / 1024.0),
Math.Round(gcmem.HighMemoryLoadThresholdBytes / 1024.0 / 1024.0));
try
{
using (Process myprocess = Process.GetCurrentProcess())
{
sb.AppendFormat(
"Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
"Process memory: Physical {0}MB \t Paged {1}MB\n",
Math.Round(myprocess.WorkingSet64 / 1024.0 / 1024.0),
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0),
Math.Round(myprocess.VirtualMemorySize64 / 1024.0 / 1024.0));
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0));
sb.AppendFormat(
"Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
"Peak process memory: Physical {0}MB \t Paged {1}MB \t\n",
Math.Round(myprocess.PeakWorkingSet64 / 1024.0 / 1024.0),
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0),
Math.Round(myprocess.PeakVirtualMemorySize64 / 1024.0 / 1024.0));
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0));
sb.AppendFormat("\nTotal process Threads {0}\n", myprocess.Threads.Count);
}
}
catch
{ }
// else
// sb.Append("Process reported as Exited \n");
return sb.ToString();
}

View File

@@ -28,6 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
@@ -188,6 +189,43 @@ namespace OpenSim.Framework.Monitoring
{
foreach (string report in GetAllStatsReports())
con.Output(report);
con.Output(MemoryReport());
}
private static string MemoryReport()
{
StringBuilder sb = new StringBuilder(Environment.NewLine);
sb.AppendFormat(
"Heap allocated: {0}MB \t allocation rate (last/avg): {1}/{2}MB/s\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0),
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1048576.0, 3),
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1048576.0, 3));
GCMemoryInfo gcmem = GC.GetGCMemoryInfo();
sb.AppendFormat(
"GCTotalCommited: {0}MB \t GCTotalAvaiable {1}MB \t GCHMthreshold {2}MB\n",
Math.Round(gcmem.TotalCommittedBytes / 1024.0 / 1024.0),
Math.Round(gcmem.TotalAvailableMemoryBytes / 1024.0 / 1024.0),
Math.Round(gcmem.HighMemoryLoadThresholdBytes / 1024.0 / 1024.0));
try
{
using (Process myprocess = Process.GetCurrentProcess())
{
sb.AppendFormat(
"Process memory: Physical {0}MB \t Paged {1}MB\n",
Math.Round(myprocess.WorkingSet64 / 1024.0 / 1024.0),
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0));
sb.AppendFormat(
"Peak process memory: Physical {0}MB \t Paged {1}MB \t\n",
Math.Round(myprocess.PeakWorkingSet64 / 1024.0 / 1024.0),
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0));
sb.AppendFormat("\nTotal process Threads {0}\n", myprocess.Threads.Count);
}
}
catch
{ }
return sb.ToString();
}
private static List<string> GetCategoryStatsReports(

View File

@@ -269,18 +269,13 @@ namespace OpenSim.Framework.Monitoring
{
lock (m_threads)
{
if (m_threads.ContainsKey(threadID))
if(RemoveThread(threadID))
{
//ThreadWatchdogInfo twi = m_threads[threadID];
//twi.Thread.Abort();
RemoveThread(threadID);
return true;
}
else
{
return false;
}
return false;
}
}
@@ -325,11 +320,8 @@ namespace OpenSim.Framework.Monitoring
{
lock (m_threads)
{
if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
return m_threads[Thread.CurrentThread.ManagedThreadId];
return m_threads.TryGetValue(Thread.CurrentThread.ManagedThreadId, out ThreadWatchdogInfo twi) ? twi : null;
}
return null;
}
/// <summary>

View File

@@ -159,17 +159,13 @@ namespace OpenSim.Framework
{
log.Info("[PLUGINS]: Loading extension point " + ext);
if (constraints.ContainsKey(ext))
if (constraints.TryGetValue(ext , out IPluginConstraint cons))
{
IPluginConstraint cons = constraints[ext];
if (cons.Apply(ext))
log.Error("[PLUGINS]: " + ext + " failed constraint: " + cons.Message);
}
IPluginFilter filter = null;
if (filters.ContainsKey(ext))
filter = filters[ext];
filters.TryGetValue(ext, out IPluginFilter filter);
List<T> loadedPlugins = new List<T>();
foreach (PluginExtensionNode node in AddinManager.GetExtensionNodes(ext))

View File

@@ -1139,12 +1139,13 @@ namespace OpenSim.Framework
UInt32.TryParse(args["region_yloc"].AsString(), out locy);
RegionLocY = locy;
}
if (args.ContainsKey("region_size_x"))
RegionSizeX = (uint)args["region_size_x"].AsInteger();
if (args.ContainsKey("region_size_y"))
RegionSizeY = (uint)args["region_size_y"].AsInteger();
if (args.ContainsKey("region_size_z"))
RegionSizeZ = (uint)args["region_size_z"].AsInteger();
OSD osdtmp;
if (args.TryGetValue("region_size_x", out osdtmp))
RegionSizeX = (uint)osdtmp.AsInteger();
if (args.TryGetValue("region_size_y", out osdtmp))
RegionSizeY = (uint)osdtmp.AsInteger();
if (args.TryGetValue("region_size_z", out osdtmp))
RegionSizeZ = (uint)osdtmp.AsInteger();
IPAddress ip_addr = null;
if (args["internal_ep_address"] != null)

View File

@@ -32,17 +32,18 @@ namespace OpenSim.Framework
{
public class RegionURI
{
private static byte[] schemaSep = osUTF8.GetASCIIBytes("://");
private static byte[] altschemaSep = osUTF8.GetASCIIBytes("|!!");
private static byte[] nameSep = osUTF8.GetASCIIBytes(":/ ");
private static byte[] altnameSep = osUTF8.GetASCIIBytes(":/ +|");
private static byte[] escapePref = osUTF8.GetASCIIBytes("+%");
private static byte[] altPortSepPref = osUTF8.GetASCIIBytes(":|");
private static readonly byte[] schemaSep = osUTF8.GetASCIIBytes("://");
private static readonly byte[] altschemaSep = osUTF8.GetASCIIBytes("|!!");
private static readonly byte[] nameSep = osUTF8.GetASCIIBytes(":/ ");
private static readonly byte[] altnameSep = osUTF8.GetASCIIBytes(":/ +|");
private static readonly byte[] escapePref = osUTF8.GetASCIIBytes("+%");
private static readonly byte[] altPortSepPref = osUTF8.GetASCIIBytes(":|");
private static readonly byte[] forbidonname = osUTF8.GetASCIIBytes(".,:;\\/");
public enum URIFlags : int
{
None = 0,
Valid = 1 << 0,
//Valid = 1 << 0,
HasHost = 1 << 1,
HasResolvedHost = 1 << 2,
HasUserName = 1 << 3,
@@ -70,7 +71,7 @@ namespace OpenSim.Framework
{
originalURI = _originalURI;
Parse(_originalURI);
if (!HasHost)
if (!HasHost && HasRegionName)
Flags |= URIFlags.IsLocalGrid;
}
@@ -81,7 +82,10 @@ namespace OpenSim.Framework
if(!HasHost)
{
Flags |= URIFlags.IsLocalGrid;
if(!HasRegionName)
Flags = URIFlags.None;
else
Flags |= URIFlags.IsLocalGrid;
return;
}
if(gi == null)
@@ -290,6 +294,12 @@ namespace OpenSim.Framework
if (tmpSlice.Length <= 0)
return;
if(tmpSlice.IndexOfAny(forbidonname) > 0)
{
Flags = URIFlags.None;
return;
}
RegionName = tmpSlice.ToString();
Flags |= URIFlags.HasRegionName;

View File

@@ -53,9 +53,9 @@ namespace OpenSim.Framework
public bool TryGet<T>(out T iface)
{
if (m_moduleInterfaces.ContainsKey(typeof(T)))
if (m_moduleInterfaces.TryGetValue(typeof(T), out object o))
{
iface = (T)m_moduleInterfaces[typeof(T)];
iface = (T)o;
return true;
}
iface = default(T);

View File

@@ -695,8 +695,8 @@ namespace OSHttpServer
m_stream.EndWrite(res);
ContextTimeoutManager.ContextLeaveActiveSend();
didleave = true;
m_currentResponse.CheckSendNextAsyncContinue();
didleave = true;
}
catch (Exception e)
{

View File

@@ -25,7 +25,7 @@ namespace OSHttpServer
public int RawBufferLen { get; set; }
public double RequestTS { get; private set; }
internal byte[] m_headerBytes = null;
internal osUTF8 m_headerBytes = null;
/// <summary>
/// Initializes a new instance of the <see cref="IHttpResponse"/> class.
@@ -228,55 +228,65 @@ namespace OSHttpServer
m_headers[name] = value;
}
public byte[] GetHeaders()
public void GetHeaders()
{
HeadersSent = true;
var sb = osStringBuilderCache.Acquire();
osUTF8 osu = OSUTF8Cached.Acquire(8 * 1024);
if(string.IsNullOrWhiteSpace(m_httpVersion))
sb.AppendFormat("HTTP/1.1 {0} {1}\r\n", (int)Status,
string.IsNullOrEmpty(Reason) ? Status.ToString() : Reason);
if (string.IsNullOrWhiteSpace(m_httpVersion))
{
osu.AppendASCII($"HTTP/1.1 {(int)Status} ");
if (string.IsNullOrEmpty(Reason))
osu.AppendASCII($"{Status}");
else
osu.Append($"{Reason}");
osu.AppendASCII("\r\n");
}
else
sb.AppendFormat("{0} {1} {2}\r\n", m_httpVersion, (int)Status,
string.IsNullOrEmpty(Reason) ? Status.ToString() : Reason);
{
osu.AppendASCII($"{m_httpVersion} {(int)Status} ");
if (string.IsNullOrEmpty(Reason))
osu.AppendASCII($"{Status}");
else
osu.Append($"{Reason}");
osu.AppendASCII("\r\n");
}
sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToString("r"));
osu.AppendASCII($"Date: {DateTime.Now:r}\r\n");
long len = 0;
if(m_body is not null)
len = m_body.Length;
if (RawBuffer is not null && RawBufferLen > 0)
long len = m_body is null ? 0 : m_body.Length;
if (RawBuffer is not null)
len += RawBufferLen;
sb.AppendFormat("Content-Length: {0}\r\n", len);
osu.AppendASCII($"Content-Length: {len}\r\n");
if (m_headers["Content-Type"] is null)
sb.AppendFormat("Content-Type: {0}\r\n", m_contentType ?? DefaultContentType);
osu.AppendASCII($"Content-Type: {m_contentType ?? DefaultContentType}\r\n");
switch(Status)
switch (Status)
{
case HttpStatusCode.OK:
case HttpStatusCode.PartialContent:
case HttpStatusCode.Accepted:
case HttpStatusCode.Continue:
case HttpStatusCode.Found:
{
int keepaliveS = m_context.TimeoutKeepAlive / 1000;
if (Connection == ConnectionType.KeepAlive && keepaliveS > 0 && m_context.MaxRequests > 0)
{
sb.AppendFormat("Keep-Alive:timeout={0}, max={1}\r\n", keepaliveS, m_context.MaxRequests);
sb.Append("Connection: Keep-Alive\r\n");
int keepaliveS = m_context.TimeoutKeepAlive / 1000;
if (Connection == ConnectionType.KeepAlive && keepaliveS > 0 && m_context.MaxRequests > 0)
{
osu.AppendASCII($"Keep-Alive:timeout={keepaliveS}, max={m_context.MaxRequests}\r\n");
osu.AppendASCII("Connection: Keep-Alive\r\n");
}
else
{
osu.AppendASCII("Connection: close\r\n");
Connection = ConnectionType.Close;
}
break;
}
else
{
sb.Append("Connection: close\r\n");
Connection = ConnectionType.Close;
}
break;
}
default:
sb.Append("Connection: close\r\n");
osu.AppendASCII("Connection: close\r\n");
Connection = ConnectionType.Close;
break;
}
@@ -284,7 +294,7 @@ namespace OSHttpServer
for (int i = 0; i < m_headers.Count; ++i)
{
string headerName = m_headers.AllKeys[i];
switch(headerName)
switch (headerName)
{
case "Connection":
case "Content-Length":
@@ -294,21 +304,27 @@ namespace OSHttpServer
continue;
}
string[] values = m_headers.GetValues(i);
if (values is null) continue;
foreach (string value in values)
sb.AppendFormat("{0}: {1}\r\n", headerName, value);
if (values is not null)
{
foreach (string value in values)
{
osu.AppendASCII($"{headerName}: ");
osu.Append($"{value}");
osu.AppendASCII("\r\n");
}
}
}
sb.Append("Server: OSWebServer\r\n");
osu.AppendASCII("Server: OSWebServer\r\n");
foreach (ResponseCookie cookie in Cookies)
sb.AppendFormat("Set-Cookie: {0}\r\n", cookie);
osu.Append($"Set-Cookie: {cookie}\r\n");
sb.Append("\r\n");
osu.AppendASCII("\r\n");
m_headers.Clear();
return Encoding.GetBytes(osStringBuilderCache.GetStringAndRelease(sb));
m_headerBytes = osu;
}
public void Send()
@@ -345,24 +361,20 @@ namespace OSHttpServer
RawBufferLen = RawBuffer.Length - RawBufferStart;
}
m_headerBytes = GetHeaders();
if (RawBufferLen == 0)
RawBuffer = null;
GetHeaders();
if (RawBuffer is not null && RawBufferLen > 0)
{
int tlen = m_headerBytes.Length + RawBufferLen;
if(tlen < 8 * 1024)
{
byte[] tmp = new byte[tlen];
Buffer.BlockCopy(m_headerBytes, 0, tmp, 0, m_headerBytes.Length);
Buffer.BlockCopy(RawBuffer, RawBufferStart, tmp, m_headerBytes.Length, RawBufferLen);
m_headerBytes = null;
RawBuffer = tmp;
RawBufferStart = 0;
RawBufferLen = tlen;
}
if (RawBufferLen == 0)
m_headerBytes.Append(RawBuffer, RawBufferStart, RawBufferLen);
RawBuffer = null;
RawBufferLen = 0;
}
}
if (m_body is not null && m_body.Length == 0)
@@ -384,11 +396,14 @@ namespace OSHttpServer
{
if (m_headerBytes is not null)
{
byte[] b = m_headerBytes;
m_headerBytes = null;
if (!m_context.SendAsyncStart(b, 0, b.Length))
if (!m_context.SendAsyncStart(m_headerBytes.GetArray(), 0, m_headerBytes.Length))
{
if(m_headerBytes is not null)
{
OSUTF8Cached.Release(m_headerBytes);
m_headerBytes = null;
}
if (m_body is not null)
{
m_body.Dispose();
@@ -499,7 +514,13 @@ namespace OSHttpServer
public void CheckSendNextAsyncContinue()
{
if(m_headerBytes is null && RawBuffer is null && m_body is null)
if (m_headerBytes is not null)
{
OSUTF8Cached.Release(m_headerBytes);
m_headerBytes = null;
}
if (m_headerBytes is null && RawBuffer is null && m_body is null)
{
Sent = true;
m_context.EndSendResponse(requestID, Connection);
@@ -512,6 +533,12 @@ namespace OSHttpServer
public void Clear()
{
if(m_headerBytes is not null)
{
OSUTF8Cached.Release(m_headerBytes);
m_headerBytes = null;
}
if(m_body is not null && m_body.CanRead)
{
m_body.Dispose();