示例#1
0
        /// <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);
        }
示例#2
0
        /// <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);
        }
示例#3
0
        public void PostLoadUnloadRequest(LoadUnloadRequest req)
        {
            lock (_outstandingLoadUnloadRequests)
            {
                _outstandingLoadUnloadRequests.AddFirst(req);
            }

            _workArrived();
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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);
        }
示例#6
0
        /// <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);
        }
示例#7
0
        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;
            }
        }
示例#8
0
        // 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);
        }
示例#9
0
        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);
        }
示例#10
0
        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;
            }
        }
示例#11
0
 /// <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);
         }
     }
 }
示例#12
0
        /// <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);
        }
示例#13
0
        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);
        }
示例#14
0
        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;
        }
示例#15
0
 /// <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;
         }
     }
 }
示例#16
0
        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;
        }
示例#17
0
        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;
            }
        }
示例#18
0
        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;
        }
示例#19
0
        // 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;
        }
示例#20
0
 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;
     }
 }
示例#21
0
        /// <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;
        }
示例#22
0
        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;
            }
        }
示例#23
0
        /// <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;
        }
示例#24
0
 private bool PerformReloadRequest(LoadUnloadRequest loadUnloadRequest)
 {
     return this.PerformLoadRequest(loadUnloadRequest);
 }
示例#25
0
 private bool PerformReloadRequest(LoadUnloadRequest loadUnloadRequest)
 {
     return(this.PerformLoadRequest(loadUnloadRequest));
 }
示例#26
0
        /// <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;
        }
示例#27
0
        public void PostLoadUnloadRequest(LoadUnloadRequest req)
        {
            lock (_outstandingLoadUnloadRequests)
            {
                _outstandingLoadUnloadRequests.AddFirst(req);
            }

            _workArrived();
        }
示例#28
0
        /// <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;
        }