Updated svn properties.
parent
b089ccfa3d
commit
b1a6f4821b
|
@ -1,313 +1,313 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* * Redistributions of source code must retain the above copyright
|
* * Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of the OpenSim Project nor the
|
* * Neither the name of the OpenSim Project nor the
|
||||||
* names of its contributors may be used to endorse or promote products
|
* names of its contributors may be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using OpenSim.Region.Environment.Interfaces;
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
using OpenSim.Region.Environment.Modules;
|
using OpenSim.Region.Environment.Modules;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
|
/// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AsyncLSLCommandManager : iScriptEngineFunctionModule
|
public class AsyncLSLCommandManager : iScriptEngineFunctionModule
|
||||||
{
|
{
|
||||||
private Thread cmdHandlerThread;
|
private Thread cmdHandlerThread;
|
||||||
private int cmdHandlerThreadCycleSleepms;
|
private int cmdHandlerThreadCycleSleepms;
|
||||||
|
|
||||||
private ScriptEngine m_ScriptEngine;
|
private ScriptEngine m_ScriptEngine;
|
||||||
|
|
||||||
public AsyncLSLCommandManager(ScriptEngine _ScriptEngine)
|
public AsyncLSLCommandManager(ScriptEngine _ScriptEngine)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = _ScriptEngine;
|
m_ScriptEngine = _ScriptEngine;
|
||||||
ReadConfig();
|
ReadConfig();
|
||||||
|
|
||||||
// Start the thread that will be doing the work
|
// Start the thread that will be doing the work
|
||||||
cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
|
cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
|
||||||
cmdHandlerThread.Name = "CmdHandlerThread";
|
cmdHandlerThread.Name = "CmdHandlerThread";
|
||||||
cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
|
cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
|
||||||
cmdHandlerThread.IsBackground = true;
|
cmdHandlerThread.IsBackground = true;
|
||||||
cmdHandlerThread.Start();
|
cmdHandlerThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadConfig()
|
public void ReadConfig()
|
||||||
{
|
{
|
||||||
cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50);
|
cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
~AsyncLSLCommandManager()
|
~AsyncLSLCommandManager()
|
||||||
{
|
{
|
||||||
// Shut down thread
|
// Shut down thread
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (cmdHandlerThread != null)
|
if (cmdHandlerThread != null)
|
||||||
{
|
{
|
||||||
if (cmdHandlerThread.IsAlive == true)
|
if (cmdHandlerThread.IsAlive == true)
|
||||||
{
|
{
|
||||||
cmdHandlerThread.Abort();
|
cmdHandlerThread.Abort();
|
||||||
cmdHandlerThread.Join();
|
cmdHandlerThread.Join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CmdHandlerThreadLoop()
|
private void CmdHandlerThreadLoop()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Check timers
|
// Check timers
|
||||||
CheckTimerEvents();
|
CheckTimerEvents();
|
||||||
Thread.Sleep(25);
|
Thread.Sleep(25);
|
||||||
// Check HttpRequests
|
// Check HttpRequests
|
||||||
CheckHttpRequests();
|
CheckHttpRequests();
|
||||||
Thread.Sleep(25);
|
Thread.Sleep(25);
|
||||||
// Check XMLRPCRequests
|
// Check XMLRPCRequests
|
||||||
CheckXMLRPCRequests();
|
CheckXMLRPCRequests();
|
||||||
Thread.Sleep(25);
|
Thread.Sleep(25);
|
||||||
// Check Listeners
|
// Check Listeners
|
||||||
CheckListeners();
|
CheckListeners();
|
||||||
Thread.Sleep(25);
|
Thread.Sleep(25);
|
||||||
|
|
||||||
// Sleep before next cycle
|
// Sleep before next cycle
|
||||||
//Thread.Sleep(cmdHandlerThreadCycleSleepms);
|
//Thread.Sleep(cmdHandlerThreadCycleSleepms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove a specific script (and all its pending commands)
|
/// Remove a specific script (and all its pending commands)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="m_localID"></param>
|
/// <param name="m_localID"></param>
|
||||||
/// <param name="m_itemID"></param>
|
/// <param name="m_itemID"></param>
|
||||||
public void RemoveScript(uint localID, LLUUID itemID)
|
public void RemoveScript(uint localID, LLUUID itemID)
|
||||||
{
|
{
|
||||||
// Remove a specific script
|
// Remove a specific script
|
||||||
|
|
||||||
// Remove from: Timers
|
// Remove from: Timers
|
||||||
UnSetTimerEvents(localID, itemID);
|
UnSetTimerEvents(localID, itemID);
|
||||||
// Remove from: HttpRequest
|
// Remove from: HttpRequest
|
||||||
IHttpRequests iHttpReq =
|
IHttpRequests iHttpReq =
|
||||||
m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
||||||
iHttpReq.StopHttpRequest(localID, itemID);
|
iHttpReq.StopHttpRequest(localID, itemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region TIMER
|
#region TIMER
|
||||||
|
|
||||||
//
|
//
|
||||||
// TIMER
|
// TIMER
|
||||||
//
|
//
|
||||||
private class TimerClass
|
private class TimerClass
|
||||||
{
|
{
|
||||||
public uint localID;
|
public uint localID;
|
||||||
public LLUUID itemID;
|
public LLUUID itemID;
|
||||||
public double interval;
|
public double interval;
|
||||||
public DateTime next;
|
public DateTime next;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TimerClass> Timers = new List<TimerClass>();
|
private List<TimerClass> Timers = new List<TimerClass>();
|
||||||
private object TimerListLock = new object();
|
private object TimerListLock = new object();
|
||||||
|
|
||||||
public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
|
public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
|
||||||
{
|
{
|
||||||
Console.WriteLine("SetTimerEvent");
|
Console.WriteLine("SetTimerEvent");
|
||||||
|
|
||||||
// Always remove first, in case this is a re-set
|
// Always remove first, in case this is a re-set
|
||||||
UnSetTimerEvents(m_localID, m_itemID);
|
UnSetTimerEvents(m_localID, m_itemID);
|
||||||
if (sec == 0) // Disabling timer
|
if (sec == 0) // Disabling timer
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Add to timer
|
// Add to timer
|
||||||
TimerClass ts = new TimerClass();
|
TimerClass ts = new TimerClass();
|
||||||
ts.localID = m_localID;
|
ts.localID = m_localID;
|
||||||
ts.itemID = m_itemID;
|
ts.itemID = m_itemID;
|
||||||
ts.interval = sec;
|
ts.interval = sec;
|
||||||
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
lock (TimerListLock)
|
lock (TimerListLock)
|
||||||
{
|
{
|
||||||
Timers.Add(ts);
|
Timers.Add(ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
|
public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
|
||||||
{
|
{
|
||||||
// Remove from timer
|
// Remove from timer
|
||||||
lock (TimerListLock)
|
lock (TimerListLock)
|
||||||
{
|
{
|
||||||
List<TimerClass> NewTimers = new List<TimerClass>();
|
List<TimerClass> NewTimers = new List<TimerClass>();
|
||||||
foreach (TimerClass ts in Timers)
|
foreach (TimerClass ts in Timers)
|
||||||
{
|
{
|
||||||
if (ts.localID != m_localID && ts.itemID != m_itemID)
|
if (ts.localID != m_localID && ts.itemID != m_itemID)
|
||||||
{
|
{
|
||||||
NewTimers.Add(ts);
|
NewTimers.Add(ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Timers.Clear();
|
Timers.Clear();
|
||||||
Timers = NewTimers;
|
Timers = NewTimers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckTimerEvents()
|
public void CheckTimerEvents()
|
||||||
{
|
{
|
||||||
// Nothing to do here?
|
// Nothing to do here?
|
||||||
if (Timers.Count == 0)
|
if (Timers.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (TimerListLock)
|
lock (TimerListLock)
|
||||||
{
|
{
|
||||||
// Go through all timers
|
// Go through all timers
|
||||||
foreach (TimerClass ts in Timers)
|
foreach (TimerClass ts in Timers)
|
||||||
{
|
{
|
||||||
// Time has passed?
|
// Time has passed?
|
||||||
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
|
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
|
||||||
{
|
{
|
||||||
// Add it to queue
|
// Add it to queue
|
||||||
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull,
|
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull,
|
||||||
new object[] {});
|
new object[] {});
|
||||||
// set next interval
|
// set next interval
|
||||||
|
|
||||||
|
|
||||||
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // lock
|
} // lock
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region HTTP REQUEST
|
#region HTTP REQUEST
|
||||||
|
|
||||||
public void CheckHttpRequests()
|
public void CheckHttpRequests()
|
||||||
{
|
{
|
||||||
if (m_ScriptEngine.World == null)
|
if (m_ScriptEngine.World == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IHttpRequests iHttpReq =
|
IHttpRequests iHttpReq =
|
||||||
m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
||||||
|
|
||||||
HttpRequestClass httpInfo = null;
|
HttpRequestClass httpInfo = null;
|
||||||
|
|
||||||
if (iHttpReq != null)
|
if (iHttpReq != null)
|
||||||
httpInfo = iHttpReq.GetNextCompletedRequest();
|
httpInfo = iHttpReq.GetNextCompletedRequest();
|
||||||
|
|
||||||
while (httpInfo != null)
|
while (httpInfo != null)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
|
//Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
|
||||||
|
|
||||||
// Deliver data to prim's remote_data handler
|
// Deliver data to prim's remote_data handler
|
||||||
//
|
//
|
||||||
// TODO: Returning null for metadata, since the lsl function
|
// TODO: Returning null for metadata, since the lsl function
|
||||||
// only returns the byte for HTTP_BODY_TRUNCATED, which is not
|
// only returns the byte for HTTP_BODY_TRUNCATED, which is not
|
||||||
// implemented here yet anyway. Should be fixed if/when maxsize
|
// implemented here yet anyway. Should be fixed if/when maxsize
|
||||||
// is supported
|
// is supported
|
||||||
|
|
||||||
object[] resobj = new object[]
|
object[] resobj = new object[]
|
||||||
{
|
{
|
||||||
httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
|
httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
|
||||||
};
|
};
|
||||||
|
|
||||||
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
||||||
httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj
|
httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj
|
||||||
);
|
);
|
||||||
|
|
||||||
httpInfo.Stop();
|
httpInfo.Stop();
|
||||||
httpInfo = null;
|
httpInfo = null;
|
||||||
|
|
||||||
httpInfo = iHttpReq.GetNextCompletedRequest();
|
httpInfo = iHttpReq.GetNextCompletedRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void CheckXMLRPCRequests()
|
public void CheckXMLRPCRequests()
|
||||||
{
|
{
|
||||||
if (m_ScriptEngine.World == null)
|
if (m_ScriptEngine.World == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
|
IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
|
||||||
|
|
||||||
if (xmlrpc != null)
|
if (xmlrpc != null)
|
||||||
{
|
{
|
||||||
while (xmlrpc.hasRequests())
|
while (xmlrpc.hasRequests())
|
||||||
{
|
{
|
||||||
RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
|
RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
|
||||||
//Console.WriteLine("PICKED REQUEST");
|
//Console.WriteLine("PICKED REQUEST");
|
||||||
|
|
||||||
//Deliver data to prim's remote_data handler
|
//Deliver data to prim's remote_data handler
|
||||||
object[] resobj = new object[]
|
object[] resobj = new object[]
|
||||||
{
|
{
|
||||||
2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty,
|
2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty,
|
||||||
rInfo.GetIntValue(),
|
rInfo.GetIntValue(),
|
||||||
rInfo.GetStrVal()
|
rInfo.GetStrVal()
|
||||||
};
|
};
|
||||||
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
||||||
rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj
|
rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckListeners()
|
public void CheckListeners()
|
||||||
{
|
{
|
||||||
if (m_ScriptEngine.World == null)
|
if (m_ScriptEngine.World == null)
|
||||||
return;
|
return;
|
||||||
IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
|
|
||||||
while (comms.HasMessages())
|
while (comms.HasMessages())
|
||||||
{
|
{
|
||||||
ListenerInfo lInfo = comms.GetNextMessage();
|
ListenerInfo lInfo = comms.GetNextMessage();
|
||||||
|
|
||||||
//Deliver data to prim's listen handler
|
//Deliver data to prim's listen handler
|
||||||
object[] resobj = new object[]
|
object[] resobj = new object[]
|
||||||
{
|
{
|
||||||
lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
|
lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
|
||||||
};
|
};
|
||||||
|
|
||||||
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
||||||
lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
|
lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If set to true then threads and stuff should try to make a graceful exit
|
/// If set to true then threads and stuff should try to make a graceful exit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool PleaseShutdown
|
public bool PleaseShutdown
|
||||||
{
|
{
|
||||||
get { return _PleaseShutdown; }
|
get { return _PleaseShutdown; }
|
||||||
set { _PleaseShutdown = value; }
|
set { _PleaseShutdown = value; }
|
||||||
}
|
}
|
||||||
private bool _PleaseShutdown = false;
|
private bool _PleaseShutdown = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,314 +1,314 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Environment.Scenes.Scripting;
|
using OpenSim.Region.Environment.Scenes.Scripting;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
|
/// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EventQueueThreadClass: iScriptEngineFunctionModule
|
public class EventQueueThreadClass: iScriptEngineFunctionModule
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many ms to sleep if queue is empty
|
/// How many ms to sleep if queue is empty
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int nothingToDoSleepms;// = 50;
|
private int nothingToDoSleepms;// = 50;
|
||||||
private ThreadPriority MyThreadPriority;
|
private ThreadPriority MyThreadPriority;
|
||||||
|
|
||||||
public long LastExecutionStarted;
|
public long LastExecutionStarted;
|
||||||
public bool InExecution = false;
|
public bool InExecution = false;
|
||||||
public bool KillCurrentScript = false;
|
public bool KillCurrentScript = false;
|
||||||
|
|
||||||
private EventQueueManager eventQueueManager;
|
private EventQueueManager eventQueueManager;
|
||||||
public Thread EventQueueThread;
|
public Thread EventQueueThread;
|
||||||
private static int ThreadCount = 0;
|
private static int ThreadCount = 0;
|
||||||
|
|
||||||
private string ScriptEngineName = "ScriptEngine.Common";
|
private string ScriptEngineName = "ScriptEngine.Common";
|
||||||
|
|
||||||
public EventQueueThreadClass(EventQueueManager eqm)
|
public EventQueueThreadClass(EventQueueManager eqm)
|
||||||
{
|
{
|
||||||
eventQueueManager = eqm;
|
eventQueueManager = eqm;
|
||||||
ReadConfig();
|
ReadConfig();
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
~EventQueueThreadClass()
|
~EventQueueThreadClass()
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ReadConfig()
|
public void ReadConfig()
|
||||||
{
|
{
|
||||||
ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName;
|
ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName;
|
||||||
nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
|
nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
|
||||||
|
|
||||||
// Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually
|
// Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually
|
||||||
string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
|
string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
|
||||||
switch (pri.ToLower())
|
switch (pri.ToLower())
|
||||||
{
|
{
|
||||||
case "lowest":
|
case "lowest":
|
||||||
MyThreadPriority = ThreadPriority.Lowest;
|
MyThreadPriority = ThreadPriority.Lowest;
|
||||||
break;
|
break;
|
||||||
case "belownormal":
|
case "belownormal":
|
||||||
MyThreadPriority = ThreadPriority.BelowNormal;
|
MyThreadPriority = ThreadPriority.BelowNormal;
|
||||||
break;
|
break;
|
||||||
case "normal":
|
case "normal":
|
||||||
MyThreadPriority = ThreadPriority.Normal;
|
MyThreadPriority = ThreadPriority.Normal;
|
||||||
break;
|
break;
|
||||||
case "abovenormal":
|
case "abovenormal":
|
||||||
MyThreadPriority = ThreadPriority.AboveNormal;
|
MyThreadPriority = ThreadPriority.AboveNormal;
|
||||||
break;
|
break;
|
||||||
case "highest":
|
case "highest":
|
||||||
MyThreadPriority = ThreadPriority.Highest;
|
MyThreadPriority = ThreadPriority.Highest;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MyThreadPriority = ThreadPriority.BelowNormal; // Default
|
MyThreadPriority = ThreadPriority.BelowNormal; // Default
|
||||||
eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngineBase", "Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\".");
|
eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngineBase", "Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\".");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now set that priority
|
// Now set that priority
|
||||||
if (EventQueueThread != null)
|
if (EventQueueThread != null)
|
||||||
if (EventQueueThread.IsAlive)
|
if (EventQueueThread.IsAlive)
|
||||||
EventQueueThread.Priority = MyThreadPriority;
|
EventQueueThread.Priority = MyThreadPriority;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start thread
|
/// Start thread
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
|
||||||
EventQueueThread = new Thread(EventQueueThreadLoop);
|
EventQueueThread = new Thread(EventQueueThreadLoop);
|
||||||
EventQueueThread.IsBackground = true;
|
EventQueueThread.IsBackground = true;
|
||||||
|
|
||||||
EventQueueThread.Priority = MyThreadPriority;
|
EventQueueThread.Priority = MyThreadPriority;
|
||||||
EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
|
EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
|
||||||
EventQueueThread.Start();
|
EventQueueThread.Start();
|
||||||
|
|
||||||
// Look at this... Don't you wish everyone did that solid coding everywhere? :P
|
// Look at this... Don't you wish everyone did that solid coding everywhere? :P
|
||||||
if (ThreadCount == int.MaxValue)
|
if (ThreadCount == int.MaxValue)
|
||||||
ThreadCount = 0;
|
ThreadCount = 0;
|
||||||
ThreadCount++;
|
ThreadCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
PleaseShutdown = true; // Set shutdown flag
|
PleaseShutdown = true; // Set shutdown flag
|
||||||
Thread.Sleep(100); // Wait a bit
|
Thread.Sleep(100); // Wait a bit
|
||||||
if (EventQueueThread != null && EventQueueThread.IsAlive == true)
|
if (EventQueueThread != null && EventQueueThread.IsAlive == true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EventQueueThread.Abort(); // Send abort
|
EventQueueThread.Abort(); // Send abort
|
||||||
EventQueueThread.Join(); // Wait for it
|
EventQueueThread.Join(); // Wait for it
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
//myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Exception killing worker thread: " + e.ToString());
|
//myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Exception killing worker thread: " + e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queue processing thread loop
|
/// Queue processing thread loop
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void EventQueueThreadLoop()
|
private void EventQueueThreadLoop()
|
||||||
{
|
{
|
||||||
//myScriptEngine.m_logger.Verbose(ScriptEngineName, "EventQueueManager Worker thread spawned");
|
//myScriptEngine.m_logger.Verbose(ScriptEngineName, "EventQueueManager Worker thread spawned");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
|
EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Every now and then check if we should shut down
|
// Every now and then check if we should shut down
|
||||||
if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0)
|
if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0)
|
||||||
{
|
{
|
||||||
// Someone should shut down, lets get exclusive lock
|
// Someone should shut down, lets get exclusive lock
|
||||||
lock (eventQueueManager.ThreadsToExitLock)
|
lock (eventQueueManager.ThreadsToExitLock)
|
||||||
{
|
{
|
||||||
// Lets re-check in case someone grabbed it
|
// Lets re-check in case someone grabbed it
|
||||||
if (eventQueueManager.ThreadsToExit > 0)
|
if (eventQueueManager.ThreadsToExit > 0)
|
||||||
{
|
{
|
||||||
// Its crowded here so we'll shut down
|
// Its crowded here so we'll shut down
|
||||||
eventQueueManager.ThreadsToExit--;
|
eventQueueManager.ThreadsToExit--;
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We have been asked to shut down
|
// We have been asked to shut down
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//try
|
//try
|
||||||
// {
|
// {
|
||||||
EventQueueManager.QueueItemStruct QIS = BlankQIS;
|
EventQueueManager.QueueItemStruct QIS = BlankQIS;
|
||||||
bool GotItem = false;
|
bool GotItem = false;
|
||||||
|
|
||||||
if (PleaseShutdown)
|
if (PleaseShutdown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (eventQueueManager.eventQueue.Count == 0)
|
if (eventQueueManager.eventQueue.Count == 0)
|
||||||
{
|
{
|
||||||
// Nothing to do? Sleep a bit waiting for something to do
|
// Nothing to do? Sleep a bit waiting for something to do
|
||||||
Thread.Sleep(nothingToDoSleepms);
|
Thread.Sleep(nothingToDoSleepms);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Something in queue, process
|
// Something in queue, process
|
||||||
//myScriptEngine.m_logger.Verbose(ScriptEngineName, "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
|
//myScriptEngine.m_logger.Verbose(ScriptEngineName, "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
|
||||||
|
|
||||||
// OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
|
// OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
|
||||||
lock (eventQueueManager.queueLock)
|
lock (eventQueueManager.queueLock)
|
||||||
{
|
{
|
||||||
GotItem = false;
|
GotItem = false;
|
||||||
for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++)
|
for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++)
|
||||||
{
|
{
|
||||||
// Get queue item
|
// Get queue item
|
||||||
QIS = eventQueueManager.eventQueue.Dequeue();
|
QIS = eventQueueManager.eventQueue.Dequeue();
|
||||||
|
|
||||||
// Check if object is being processed by someone else
|
// Check if object is being processed by someone else
|
||||||
if (eventQueueManager.TryLock(QIS.localID) == false)
|
if (eventQueueManager.TryLock(QIS.localID) == false)
|
||||||
{
|
{
|
||||||
// Object is already being processed, requeue it
|
// Object is already being processed, requeue it
|
||||||
eventQueueManager.eventQueue.Enqueue(QIS);
|
eventQueueManager.eventQueue.Enqueue(QIS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We have lock on an object and can process it
|
// We have lock on an object and can process it
|
||||||
GotItem = true;
|
GotItem = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // go through queue
|
} // go through queue
|
||||||
} // lock
|
} // lock
|
||||||
|
|
||||||
if (GotItem == true)
|
if (GotItem == true)
|
||||||
{
|
{
|
||||||
// Execute function
|
// Execute function
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
eventQueueManager.m_ScriptEngine.Log.Debug(ScriptEngineName,
|
eventQueueManager.m_ScriptEngine.Log.Debug(ScriptEngineName,
|
||||||
"Executing event:\r\n"
|
"Executing event:\r\n"
|
||||||
+ "QIS.localID: " + QIS.localID
|
+ "QIS.localID: " + QIS.localID
|
||||||
+ ", QIS.itemID: " + QIS.itemID
|
+ ", QIS.itemID: " + QIS.itemID
|
||||||
+ ", QIS.functionName: " +
|
+ ", QIS.functionName: " +
|
||||||
QIS.functionName);
|
QIS.functionName);
|
||||||
#endif
|
#endif
|
||||||
LastExecutionStarted = DateTime.Now.Ticks;
|
LastExecutionStarted = DateTime.Now.Ticks;
|
||||||
KillCurrentScript = false;
|
KillCurrentScript = false;
|
||||||
InExecution = true;
|
InExecution = true;
|
||||||
eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID,
|
eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID,
|
||||||
QIS.itemID,
|
QIS.itemID,
|
||||||
QIS.functionName,
|
QIS.functionName,
|
||||||
QIS.llDetectParams,
|
QIS.llDetectParams,
|
||||||
QIS.param);
|
QIS.param);
|
||||||
InExecution = false;
|
InExecution = false;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
InExecution = false;
|
InExecution = false;
|
||||||
// DISPLAY ERROR INWORLD
|
// DISPLAY ERROR INWORLD
|
||||||
string text = "Error executing script function \"" + QIS.functionName +
|
string text = "Error executing script function \"" + QIS.functionName +
|
||||||
"\":\r\n";
|
"\":\r\n";
|
||||||
if (e.InnerException != null)
|
if (e.InnerException != null)
|
||||||
{
|
{
|
||||||
// Send inner exception
|
// Send inner exception
|
||||||
text += e.InnerException.Message.ToString();
|
text += e.InnerException.Message.ToString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text += "\r\n";
|
text += "\r\n";
|
||||||
// Send normal
|
// Send normal
|
||||||
text += e.Message.ToString();
|
text += e.Message.ToString();
|
||||||
}
|
}
|
||||||
if (KillCurrentScript)
|
if (KillCurrentScript)
|
||||||
text += "\r\nScript will be deactivated!";
|
text += "\r\nScript will be deactivated!";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (text.Length > 1500)
|
if (text.Length > 1500)
|
||||||
text = text.Substring(0, 1500);
|
text = text.Substring(0, 1500);
|
||||||
IScriptHost m_host =
|
IScriptHost m_host =
|
||||||
eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
|
eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
|
||||||
//if (m_host != null)
|
//if (m_host != null)
|
||||||
//{
|
//{
|
||||||
eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text),
|
eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text),
|
||||||
ChatTypeEnum.Say, 0,
|
ChatTypeEnum.Say, 0,
|
||||||
m_host.AbsolutePosition,
|
m_host.AbsolutePosition,
|
||||||
m_host.Name, m_host.UUID);
|
m_host.Name, m_host.UUID);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//}
|
//}
|
||||||
//else
|
//else
|
||||||
//{
|
//{
|
||||||
// T oconsole
|
// T oconsole
|
||||||
eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName,
|
eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName,
|
||||||
"Unable to send text in-world:\r\n" +
|
"Unable to send text in-world:\r\n" +
|
||||||
text);
|
text);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// So we are done sending message in-world
|
// So we are done sending message in-world
|
||||||
if (KillCurrentScript)
|
if (KillCurrentScript)
|
||||||
{
|
{
|
||||||
eventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript(
|
eventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript(
|
||||||
QIS.localID, QIS.itemID);
|
QIS.localID, QIS.itemID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
InExecution = false;
|
InExecution = false;
|
||||||
eventQueueManager.ReleaseLock(QIS.localID);
|
eventQueueManager.ReleaseLock(QIS.localID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Something in queue
|
} // Something in queue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ThreadAbortException tae)
|
catch (ThreadAbortException tae)
|
||||||
{
|
{
|
||||||
eventQueueManager.m_ScriptEngine.Log.Notice(ScriptEngineName, "ThreadAbortException while executing function.");
|
eventQueueManager.m_ScriptEngine.Log.Notice(ScriptEngineName, "ThreadAbortException while executing function.");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName, "Exception in EventQueueThreadLoop: " + e.ToString());
|
eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName, "Exception in EventQueueThreadLoop: " + e.ToString());
|
||||||
}
|
}
|
||||||
} // while
|
} // while
|
||||||
} // try
|
} // try
|
||||||
catch (ThreadAbortException)
|
catch (ThreadAbortException)
|
||||||
{
|
{
|
||||||
//myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Worker thread killed: " + tae.Message);
|
//myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Worker thread killed: " + tae.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If set to true then threads and stuff should try to make a graceful exit
|
/// If set to true then threads and stuff should try to make a graceful exit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool PleaseShutdown
|
public bool PleaseShutdown
|
||||||
{
|
{
|
||||||
get { return _PleaseShutdown; }
|
get { return _PleaseShutdown; }
|
||||||
set { _PleaseShutdown = value; }
|
set { _PleaseShutdown = value; }
|
||||||
}
|
}
|
||||||
private bool _PleaseShutdown = false;
|
private bool _PleaseShutdown = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,163 +1,163 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class does maintenance on script engine.
|
/// This class does maintenance on script engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MaintenanceThread : iScriptEngineFunctionModule
|
public class MaintenanceThread : iScriptEngineFunctionModule
|
||||||
{
|
{
|
||||||
public ScriptEngine m_ScriptEngine;
|
public ScriptEngine m_ScriptEngine;
|
||||||
private int MaintenanceLoopms;
|
private int MaintenanceLoopms;
|
||||||
|
|
||||||
public MaintenanceThread(ScriptEngine _ScriptEngine)
|
public MaintenanceThread(ScriptEngine _ScriptEngine)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = _ScriptEngine;
|
m_ScriptEngine = _ScriptEngine;
|
||||||
|
|
||||||
ReadConfig();
|
ReadConfig();
|
||||||
|
|
||||||
// Start maintenance thread
|
// Start maintenance thread
|
||||||
StartMaintenanceThread();
|
StartMaintenanceThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
~MaintenanceThread()
|
~MaintenanceThread()
|
||||||
{
|
{
|
||||||
StopMaintenanceThread();
|
StopMaintenanceThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadConfig()
|
public void ReadConfig()
|
||||||
{
|
{
|
||||||
MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
|
MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#region " Maintenance thread "
|
#region " Maintenance thread "
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maintenance thread. Enforcing max execution time for example.
|
/// Maintenance thread. Enforcing max execution time for example.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Thread MaintenanceThreadThread;
|
public Thread MaintenanceThreadThread;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts maintenance thread
|
/// Starts maintenance thread
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void StartMaintenanceThread()
|
private void StartMaintenanceThread()
|
||||||
{
|
{
|
||||||
if (MaintenanceThreadThread == null)
|
if (MaintenanceThreadThread == null)
|
||||||
{
|
{
|
||||||
MaintenanceThreadThread = new Thread(MaintenanceLoop);
|
MaintenanceThreadThread = new Thread(MaintenanceLoop);
|
||||||
MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
|
MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
|
||||||
MaintenanceThreadThread.IsBackground = true;
|
MaintenanceThreadThread.IsBackground = true;
|
||||||
MaintenanceThreadThread.Start();
|
MaintenanceThreadThread.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops maintenance thread
|
/// Stops maintenance thread
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void StopMaintenanceThread()
|
private void StopMaintenanceThread()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
m_ScriptEngine.Log.Debug(m_ScriptEngine.ScriptEngineName, "StopMaintenanceThread() called");
|
m_ScriptEngine.Log.Debug(m_ScriptEngine.ScriptEngineName, "StopMaintenanceThread() called");
|
||||||
#endif
|
#endif
|
||||||
PleaseShutdown = true;
|
PleaseShutdown = true;
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (MaintenanceThreadThread != null)
|
if (MaintenanceThreadThread != null)
|
||||||
{
|
{
|
||||||
if (MaintenanceThreadThread.IsAlive)
|
if (MaintenanceThreadThread.IsAlive)
|
||||||
{
|
{
|
||||||
MaintenanceThreadThread.Abort();
|
MaintenanceThreadThread.Abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception stopping maintenence thread: " + ex.ToString());
|
m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception stopping maintenence thread: " + ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A thread should run in this loop and check all running scripts
|
/// A thread should run in this loop and check all running scripts
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void MaintenanceLoop()
|
public void MaintenanceLoop()
|
||||||
{
|
{
|
||||||
if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms)
|
if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms)
|
||||||
m_ScriptEngine.Log.Warn(m_ScriptEngine.ScriptEngineName,
|
m_ScriptEngine.Log.Warn(m_ScriptEngine.ScriptEngineName,
|
||||||
"Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run.");
|
"Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run.");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks;
|
long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks;
|
||||||
long Last_ReReadConfigFilens = DateTime.Now.Ticks;
|
long Last_ReReadConfigFilens = DateTime.Now.Ticks;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep before next pass
|
System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep before next pass
|
||||||
if (PleaseShutdown)
|
if (PleaseShutdown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_ScriptEngine != null)
|
if (m_ScriptEngine != null)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Re-reading config every x seconds
|
// Re-reading config every x seconds
|
||||||
//
|
//
|
||||||
if (m_ScriptEngine.RefreshConfigFileSeconds > 0)
|
if (m_ScriptEngine.RefreshConfigFileSeconds > 0)
|
||||||
{
|
{
|
||||||
// Check if its time to re-read config
|
// Check if its time to re-read config
|
||||||
if (DateTime.Now.Ticks - Last_ReReadConfigFilens > m_ScriptEngine.RefreshConfigFilens)
|
if (DateTime.Now.Ticks - Last_ReReadConfigFilens > m_ScriptEngine.RefreshConfigFilens)
|
||||||
{
|
{
|
||||||
// Its time to re-read config file
|
// Its time to re-read config file
|
||||||
m_ScriptEngine.ReadConfig();
|
m_ScriptEngine.ReadConfig();
|
||||||
Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
|
Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Adjust number of running script threads if not correct
|
// Adjust number of running script threads if not correct
|
||||||
//
|
//
|
||||||
if (m_ScriptEngine.m_EventQueueManager != null)
|
if (m_ScriptEngine.m_EventQueueManager != null)
|
||||||
m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
|
m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if any script has exceeded its max execution time
|
// Check if any script has exceeded its max execution time
|
||||||
//
|
//
|
||||||
if (m_ScriptEngine.m_EventQueueManager != null && m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime)
|
if (m_ScriptEngine.m_EventQueueManager != null && m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime)
|
||||||
{
|
{
|
||||||
// We are enforcing execution time
|
// We are enforcing execution time
|
||||||
if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
|
if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
|
||||||
m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens)
|
m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens)
|
||||||
{
|
{
|
||||||
// Its time to check again
|
// Its time to check again
|
||||||
m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
|
m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
|
||||||
Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
|
Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // m_ScriptEngine != null
|
} // m_ScriptEngine != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: " + ex.ToString());
|
m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: " + ex.ToString());
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If set to true then threads and stuff should try to make a graceful exit
|
/// If set to true then threads and stuff should try to make a graceful exit
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool PleaseShutdown
|
public bool PleaseShutdown
|
||||||
{
|
{
|
||||||
get { return _PleaseShutdown; }
|
get { return _PleaseShutdown; }
|
||||||
set { _PleaseShutdown = value; }
|
set { _PleaseShutdown = value; }
|
||||||
}
|
}
|
||||||
private bool _PleaseShutdown = false;
|
private bool _PleaseShutdown = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
|
||||||
{
|
{
|
||||||
public interface iScriptEngineFunctionModule
|
public interface iScriptEngineFunctionModule
|
||||||
{
|
{
|
||||||
void ReadConfig();
|
void ReadConfig();
|
||||||
bool PleaseShutdown { get; set; }
|
bool PleaseShutdown { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,63 +1,63 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid>
|
<ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>OpenSim._32BitLaunch</RootNamespace>
|
<RootNamespace>OpenSim._32BitLaunch</RootNamespace>
|
||||||
<AssemblyName>OpenSim.32BitLaunch</AssemblyName>
|
<AssemblyName>OpenSim.32BitLaunch</AssemblyName>
|
||||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>..\..\..\bin\</OutputPath>
|
<OutputPath>..\..\..\bin\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Xml.Linq">
|
<Reference Include="System.Xml.Linq">
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Data.DataSetExtensions">
|
<Reference Include="System.Data.DataSetExtensions">
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Region\Application\OpenSim.csproj">
|
<ProjectReference Include="..\..\Region\Application\OpenSim.csproj">
|
||||||
<Project>{AC9EB8AB-0000-0000-0000-000000000000}</Project>
|
<Project>{AC9EB8AB-0000-0000-0000-000000000000}</Project>
|
||||||
<Name>OpenSim</Name>
|
<Name>OpenSim</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
|
@ -1,10 +1,10 @@
|
||||||
namespace OpenSim._32BitLaunch
|
namespace OpenSim._32BitLaunch
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
OpenSim.Application.Main(args);
|
OpenSim.Application.Main(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
// General Information about an assembly is controlled through the following
|
||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("OpenSim.32BitLaunch")]
|
[assembly: AssemblyTitle("OpenSim.32BitLaunch")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Microsoft")]
|
[assembly: AssemblyCompany("Microsoft")]
|
||||||
[assembly: AssemblyProduct("OpenSim.32BitLaunch")]
|
[assembly: AssemblyProduct("OpenSim.32BitLaunch")]
|
||||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2008")]
|
[assembly: AssemblyCopyright("Copyright © Microsoft 2008")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
// to COM components. If you need to access a type in this assembly from
|
// to COM components. If you need to access a type in this assembly from
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
[assembly: Guid("5072e919-46ab-47e6-8a63-08108324ccdf")]
|
[assembly: Guid("5072e919-46ab-47e6-8a63-08108324ccdf")]
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
// Version information for an assembly consists of the following four values:
|
||||||
//
|
//
|
||||||
// Major Version
|
// Major Version
|
||||||
// Minor Version
|
// Minor Version
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
|
|
@ -60,6 +60,7 @@ property_map = {
|
||||||
".mdp" : textfile,
|
".mdp" : textfile,
|
||||||
".mds" : textfile,
|
".mds" : textfile,
|
||||||
".nsi" : textfile,
|
".nsi" : textfile,
|
||||||
|
".pdb" : binary,
|
||||||
".php" : script,
|
".php" : script,
|
||||||
".pidb" : binary,
|
".pidb" : binary,
|
||||||
".pl" : script,
|
".pl" : script,
|
||||||
|
|
Loading…
Reference in New Issue