/// <summary> /// This function attempts to load a script from the unloaded script cache /// </summary> /// <param name="scriptAssetId">The asset ID for the script to be loaded</param> /// <param name="lrq">The request that is causing the load</param> /// <returns></returns> private bool TryStartScriptFromUnloadedCache(UUID scriptAssetId, LoadUnloadRequest lrq) { CompiledScript compiledScript; if (_unloadedScriptCache.TryGetValue(scriptAssetId, out compiledScript)) { _log.InfoFormat("[Phlox]: Starting recovered script {0} in item {1} group {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.LocalId, lrq.Prim.LocalId); //remove the script from the unloaded cache for good measure since it is now loaded again _unloadedScriptCache.Remove(scriptAssetId); //check the part in the load request for this script. //even though we're not using the passed in script asset, //we should still do cleanup ClearSerializedScriptData(lrq, scriptAssetId); BeginScriptRun(lrq, compiledScript); _loadedScripts[scriptAssetId] = new LoadedScript { Script = compiledScript, RefCount = 1 }; return(true); } return(false); }
/// <summary> /// If the script asset is found cached, we start a new instance of it /// </summary> /// <param name="scriptAssetId"></param> /// <returns></returns> private bool TryStartSharedScript(UUID scriptAssetId, LoadUnloadRequest loadRequest) { LoadedScript script; if (_loadedScripts.TryGetValue(scriptAssetId, out script)) { //only adjust ref counts if this is not a reload if (loadRequest.RequestType != LoadUnloadRequest.LUType.Reload) { script.RefCount++; } //check the part in the load request for this script. //even though we're not using the passed in script asset, //we should still do cleanup ClearSerializedScriptData(loadRequest, scriptAssetId); _log.InfoFormat("[Phlox]: Starting shared script {0} in item {1} owner {2} part {3}", scriptAssetId, loadRequest.ItemId, loadRequest.Prim.ParentGroup.OwnerID, loadRequest.Prim.LocalId); BeginScriptRun(loadRequest, script.Script); return(true); } return(false); }
public void PostLoadUnloadRequest(LoadUnloadRequest req) { lock (_outstandingLoadUnloadRequests) { _outstandingLoadUnloadRequests.AddFirst(req); } _workArrived(); }
private UUID FindAssetId(LoadUnloadRequest lrq) { TaskInventoryItem item = lrq.Prim.Inventory.GetInventoryItem(lrq.ItemId); if (item == null) { _log.ErrorFormat("[Phlox]: Could not find inventory item {0} in primitive {1} ({2}) to start script", lrq.ItemId, lrq.Prim.Name, lrq.Prim.UUID); return(UUID.Zero); } else { return(item.AssetID); } }
private bool SubmitAssetLoadRequest(LoadUnloadRequest lrq) { UUID scriptAssetId = this.FindAssetId(lrq); if (scriptAssetId != UUID.Zero) { if (AddAssetWait(scriptAssetId, lrq)) { _assetCache.GetAsset(scriptAssetId, delegate(UUID i, AssetBase a) { this.AssetReceived(lrq.Prim.LocalId, lrq.ItemId, i, a); }, AssetRequestInfo.InternalRequest()); } return(true); } return(false); }
/// <summary> /// Try to load a script from disk and start it up /// </summary> /// <param name="scriptAssetId"></param> /// <param name="lrq"></param> /// <returns></returns> private bool TryStartCachedScript(UUID scriptAssetId, LoadUnloadRequest lrq) { //check in the cache directory for compiled scripts if (ScriptIsCached(scriptAssetId)) { CompiledScript script = LoadScriptFromDisk(scriptAssetId); _log.InfoFormat("[Phlox]: Starting cached script {0} in item {1} owner {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.OwnerID, lrq.Prim.LocalId); BeginScriptRun(lrq, script); _loadedScripts[scriptAssetId] = new LoadedScript { Script = script, RefCount = 1 }; return(true); } return(false); }
private void ClearSerializedScriptData(LoadUnloadRequest loadRequest, UUID scriptAssetId) { Dictionary <UUID, byte[]> dictionary = loadRequest.Prim.SerializedScriptByteCode; if (dictionary == null) { return; } if (dictionary.ContainsKey(scriptAssetId)) { dictionary.Remove(scriptAssetId); } if (dictionary.Count == 0) { loadRequest.Prim.SerializedScriptByteCode = null; } }
// Returns true if it found the script loaded and decremented the refcount. private bool PerformUnloadRequest(LoadUnloadRequest unloadReq) { bool rc = false; // Find based on the item ID VM.Interpreter loadedScript = _exeScheduler.FindScript(unloadReq.ItemId); if (loadedScript != null) { LoadedScript reffedScript; //tell the scheduler the script needs to be pulled _exeScheduler.DoUnload(unloadReq.ItemId, unloadReq); //tell the async command manager that it needs to remove this script AsyncCommandManager.RemoveScript(_engineInterface, unloadReq.LocalId, unloadReq.ItemId); //tell the state manager to remove this script _stateManager.ScriptUnloaded(unloadReq.ItemId); //decref and unload if refcount is 0 based on the Asset ID if (_loadedScripts.TryGetValue(loadedScript.Script.AssetId, out reffedScript)) { if (--reffedScript.RefCount == 0) { _loadedScripts.Remove(loadedScript.Script.AssetId); _unloadedScriptCache.Add(loadedScript.Script.AssetId, loadedScript.Script); } rc = true; } } // Callback here because if the Item ID was not found, the callback would be meaningless if (unloadReq.PostUnloadCallback != null) { // Now call the completion callback (e.g. now that it is safe for the script to be removed in the delete case). unloadReq.PostUnloadCallback(unloadReq.Prim, unloadReq.ItemId, unloadReq.CallbackParams.AllowedDrop, unloadReq.CallbackParams.FireEvents, unloadReq.CallbackParams.ReplaceArgs); } return(rc); }
private bool PerformLoadRequest(LoadUnloadRequest lrq) { //look up the asset id UUID scriptAssetId = this.FindAssetId(lrq); if (scriptAssetId != UUID.Zero) { try { //we try to load a script the most efficient way possible. //these if statements are ordered from most efficient to least if (TryStartSharedScript(scriptAssetId, lrq)) { return(true); } else if (TryStartScriptFromUnloadedCache(scriptAssetId, lrq)) { return(true); } else if (TryStartScriptFromSerializedData(scriptAssetId, lrq)) { return(true); } else if (TryStartCachedScript(scriptAssetId, lrq)) { return(true); } else { SubmitAssetLoadRequest(lrq); return(true); } } catch (LoaderException e) { _log.ErrorFormat("[Phlox]: Could not load script: " + e.Message); } } return(false); }
private void BeginScriptRun(LoadUnloadRequest lrq, CompiledScript script) { RuntimeState state = this.TryLoadState(lrq); //if this is a reload, we unload first if (lrq.RequestType == LoadUnloadRequest.LUType.Reload) { this.PerformUnloadRequest(lrq); } try { _exeScheduler.FinishedLoading(lrq, script, state); } catch (Exception e) { _log.ErrorFormat("[Phlox]: Error when informing scheduler of script load. Script: {0} Item: {1} Group: {2} Part: {3}. {4}", script.AssetId, lrq.ItemId, lrq.Prim.ParentGroup.LocalId, lrq.Prim.LocalId, e); throw; } }
/// <summary> /// Tracks a wait on the asset server /// </summary> /// <param name="scriptAssetId"></param> /// <param name="lrq"></param> /// <returns>True if a request should be sent, false if not (already in progress)</returns> private bool AddAssetWait(UUID scriptAssetId, LoadUnloadRequest lrq) { lock (_assetAndCompileLock) { List <LoadUnloadRequest> waitingRequests; if (_waitingForAssetServer.TryGetValue(scriptAssetId, out waitingRequests)) { //we already have another script waiting for load with the same UUID, //add this one to the waiting list waitingRequests.Add(lrq); return(false); } else { //no one waiting for this asset yet, create a new entry _waitingForAssetServer.Add(scriptAssetId, new List <LoadUnloadRequest>() { lrq }); return(true); } } }
/// <summary> /// Attempt to load state from the correct source /// </summary> /// <param name="loadRequest">The request that sparked the script load</param> /// <returns>The runtime state or null</returns> private RuntimeState TryLoadState(LoadUnloadRequest loadRequest) { try { switch (loadRequest.StateSource) { case OpenSim.Region.Framework.ScriptStateSource.RegionLocalDisk: return(_stateManager.LoadStateFromDisk(loadRequest.ItemId)); case OpenSim.Region.Framework.ScriptStateSource.PrimData: return(_stateManager.LoadStateFromPrim(loadRequest.ItemId, loadRequest.OldItemId, loadRequest.Prim)); } return(null); } catch (Exception e) { _log.ErrorFormat("[Phlox]: Loading script state failed for {0}, {1}", loadRequest.ItemId, e); } return(null); }
private bool TryStartScriptFromSerializedData(UUID scriptAssetId, LoadUnloadRequest lrq) { if (lrq.Prim.SerializedScriptByteCode == null) { return(false); } byte[] serializedCompiledScript; if (lrq.Prim.SerializedScriptByteCode.TryGetValue(scriptAssetId, out serializedCompiledScript)) { //deserialize and load using (MemoryStream ms = new MemoryStream(serializedCompiledScript)) { Serialization.SerializedScript script = ProtoBuf.Serializer.Deserialize <Serialization.SerializedScript>(ms); if (script == null) { _log.ErrorFormat("[Phlox]: LOADER: Script data contained in prim failed to deserialize"); ClearSerializedScriptData(lrq, scriptAssetId); return(false); } else { CompiledScript compiledScript = script.ToCompiledScript(); _log.InfoFormat("[Phlox]: Starting contained script {0} in item {1} group {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.LocalId, lrq.Prim.LocalId); BeginScriptRun(lrq, compiledScript); _loadedScripts[scriptAssetId] = new LoadedScript { Script = compiledScript, RefCount = 1 }; return(true); } } } return(false); }
private bool SubmitAssetLoadRequest(LoadUnloadRequest lrq) { UUID scriptAssetId = this.FindAssetId(lrq); if (scriptAssetId != UUID.Zero) { if (AddAssetWait(scriptAssetId, lrq)) { _assetCache.GetAsset(scriptAssetId, delegate(UUID i, AssetBase a) { this.AssetReceived(lrq.Prim.LocalId, lrq.ItemId, i, a); }, AssetRequestInfo.InternalRequest()); } return true; } return false; }
/// <summary> /// Tracks a wait on the asset server /// </summary> /// <param name="scriptAssetId"></param> /// <param name="lrq"></param> /// <returns>True if a request should be sent, false if not (already in progress)</returns> private bool AddAssetWait(UUID scriptAssetId, LoadUnloadRequest lrq) { lock (_assetAndCompileLock) { List<LoadUnloadRequest> waitingRequests; if (_waitingForAssetServer.TryGetValue(scriptAssetId, out waitingRequests)) { //we already have another script waiting for load with the same UUID, //add this one to the waiting list waitingRequests.Add(lrq); return false; } else { //no one waiting for this asset yet, create a new entry _waitingForAssetServer.Add(scriptAssetId, new List<LoadUnloadRequest>() { lrq }); return true; } } }
private bool PerformLoadRequest(LoadUnloadRequest lrq) { //look up the asset id UUID scriptAssetId = this.FindAssetId(lrq); if (scriptAssetId != UUID.Zero) { try { //we try to load a script the most efficient way possible. //these if statements are ordered from most efficient to least if (TryStartSharedScript(scriptAssetId, lrq)) { return true; } else if (TryStartScriptFromUnloadedCache(scriptAssetId, lrq)) { return true; } else if (TryStartScriptFromSerializedData(scriptAssetId, lrq)) { return true; } else if (TryStartCachedScript(scriptAssetId, lrq)) { return true; } else { SubmitAssetLoadRequest(lrq); return true; } } catch (LoaderException e) { _log.ErrorFormat("[Phlox]: Could not load script: " + e.Message); } } return false; }
private bool TryStartScriptFromSerializedData(UUID scriptAssetId, LoadUnloadRequest lrq) { if (lrq.Prim.SerializedScriptByteCode == null) return false; byte[] serializedCompiledScript; if (lrq.Prim.SerializedScriptByteCode.TryGetValue(scriptAssetId, out serializedCompiledScript)) { //deserialize and load using (MemoryStream ms = new MemoryStream(serializedCompiledScript)) { Serialization.SerializedScript script = ProtoBuf.Serializer.Deserialize<Serialization.SerializedScript>(ms); if (script == null) { _log.ErrorFormat("[Phlox]: LOADER: Script data contained in prim failed to deserialize"); ClearSerializedScriptData(lrq, scriptAssetId); return false; } else { CompiledScript compiledScript = script.ToCompiledScript(); _log.InfoFormat("[Phlox]: Starting contained script {0} in item {1} group {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.LocalId, lrq.Prim.LocalId); BeginScriptRun(lrq, compiledScript); _loadedScripts[scriptAssetId] = new LoadedScript { Script = compiledScript, RefCount = 1 }; return true; } } } return false; }
// Returns true if it found the script loaded and decremented the refcount. private bool PerformUnloadRequest(LoadUnloadRequest unloadReq) { bool rc = false; // Find based on the item ID VM.Interpreter loadedScript = _exeScheduler.FindScript(unloadReq.ItemId); if (loadedScript != null) { LoadedScript reffedScript; //tell the scheduler the script needs to be pulled _exeScheduler.DoUnload(unloadReq.ItemId, unloadReq); //tell the async command manager that it needs to remove this script AsyncCommandManager.RemoveScript(_engineInterface, unloadReq.LocalId, unloadReq.ItemId); //tell the state manager to remove this script _stateManager.ScriptUnloaded(unloadReq.ItemId); //decref and unload if refcount is 0 based on the Asset ID if (_loadedScripts.TryGetValue(loadedScript.Script.AssetId, out reffedScript)) { if (--reffedScript.RefCount == 0) { _loadedScripts.Remove(loadedScript.Script.AssetId); _unloadedScriptCache.Add(loadedScript.Script.AssetId, loadedScript.Script); } rc = true; } // Callback here because if the Item ID was not found, the callback would be meaningless if (unloadReq.PostUnloadCallback != null) { // Now call the completion callback (e.g. now that it is safe for the script to be removed in the delete case). unloadReq.PostUnloadCallback(unloadReq.Prim, unloadReq.ItemId, unloadReq.CallbackParams.AllowedDrop, unloadReq.CallbackParams.FireEvents, unloadReq.CallbackParams.ReplaceArgs); } } return rc; }
private UUID FindAssetId(LoadUnloadRequest lrq) { TaskInventoryItem item = lrq.Prim.Inventory.GetInventoryItem(lrq.ItemId); if (item == null) { _log.ErrorFormat("[Phlox]: Could not find inventory item {0} in primitive {1} ({2}) to start script", lrq.ItemId, lrq.Prim.Name, lrq.Prim.UUID); return UUID.Zero; } else { return item.AssetID; } }
/// <summary> /// Attempt to load state from the correct source /// </summary> /// <param name="loadRequest">The request that sparked the script load</param> /// <returns>The runtime state or null</returns> private RuntimeState TryLoadState(LoadUnloadRequest loadRequest) { try { switch (loadRequest.StateSource) { case OpenSim.Region.Framework.ScriptStateSource.RegionLocalDisk: return _stateManager.LoadStateFromDisk(loadRequest.ItemId); case OpenSim.Region.Framework.ScriptStateSource.PrimData: return _stateManager.LoadStateFromPrim(loadRequest.ItemId, loadRequest.OldItemId, loadRequest.Prim); } return null; } catch (Exception e) { _log.ErrorFormat("[Phlox]: Loading script state failed for {0}, {1}", loadRequest.ItemId, e); } return null; }
private void ClearSerializedScriptData(LoadUnloadRequest loadRequest, UUID scriptAssetId) { Dictionary<UUID, byte[]> dictionary = loadRequest.Prim.SerializedScriptByteCode; if (dictionary == null) return; if (dictionary.ContainsKey(scriptAssetId)) { dictionary.Remove(scriptAssetId); } if (dictionary.Count == 0) { loadRequest.Prim.SerializedScriptByteCode = null; } }
/// <summary> /// If the script asset is found cached, we start a new instance of it /// </summary> /// <param name="scriptAssetId"></param> /// <returns></returns> private bool TryStartSharedScript(UUID scriptAssetId, LoadUnloadRequest loadRequest) { LoadedScript script; if (_loadedScripts.TryGetValue(scriptAssetId, out script)) { //only adjust ref counts if this is not a reload if (loadRequest.RequestType != LoadUnloadRequest.LUType.Reload) { script.RefCount++; } //check the part in the load request for this script. //even though we're not using the passed in script asset, //we should still do cleanup ClearSerializedScriptData(loadRequest, scriptAssetId); _log.InfoFormat("[Phlox]: Starting shared script {0} in item {1} owner {2} part {3}", scriptAssetId, loadRequest.ItemId, loadRequest.Prim.ParentGroup.OwnerID, loadRequest.Prim.LocalId); BeginScriptRun(loadRequest, script.Script); return true; } return false; }
private bool PerformReloadRequest(LoadUnloadRequest loadUnloadRequest) { return this.PerformLoadRequest(loadUnloadRequest); }
private bool PerformReloadRequest(LoadUnloadRequest loadUnloadRequest) { return(this.PerformLoadRequest(loadUnloadRequest)); }
/// <summary> /// Try to load a script from disk and start it up /// </summary> /// <param name="scriptAssetId"></param> /// <param name="lrq"></param> /// <returns></returns> private bool TryStartCachedScript(UUID scriptAssetId, LoadUnloadRequest lrq) { //check in the cache directory for compiled scripts if (ScriptIsCached(scriptAssetId)) { CompiledScript script = LoadScriptFromDisk(scriptAssetId); _log.InfoFormat("[Phlox]: Starting cached script {0} in item {1} owner {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.OwnerID, lrq.Prim.LocalId); BeginScriptRun(lrq, script); _loadedScripts[scriptAssetId] = new LoadedScript { Script = script, RefCount = 1 }; return true; } return false; }
/// <summary> /// This function attempts to load a script from the unloaded script cache /// </summary> /// <param name="scriptAssetId">The asset ID for the script to be loaded</param> /// <param name="lrq">The request that is causing the load</param> /// <returns></returns> private bool TryStartScriptFromUnloadedCache(UUID scriptAssetId, LoadUnloadRequest lrq) { CompiledScript compiledScript; if (_unloadedScriptCache.TryGetValue(scriptAssetId, out compiledScript)) { _log.InfoFormat("[Phlox]: Starting recovered script {0} in item {1} group {2} part {3}", scriptAssetId, lrq.ItemId, lrq.Prim.ParentGroup.LocalId, lrq.Prim.LocalId); //remove the script from the unloaded cache for good measure since it is now loaded again _unloadedScriptCache.Remove(scriptAssetId); //check the part in the load request for this script. //even though we're not using the passed in script asset, //we should still do cleanup ClearSerializedScriptData(lrq, scriptAssetId); BeginScriptRun(lrq, compiledScript); _loadedScripts[scriptAssetId] = new LoadedScript { Script = compiledScript, RefCount = 1 }; return true; } return false; }