private void AddInCleanup(VModule moduleStopped)
        {

            //cleanup 
            if (Constants.ModuleIsolationLevel == ModuleIsolationModes.AppDomain)
            {
                logger.Log("AppDomain cleanup for "+ moduleStopped.GetInfo().AppName());
                bool done = false;
                AddInController aiController = AddInController.GetAddInController(moduleStopped);
                SafeThread t = new SafeThread(delegate()
                {
                    while (!done)
                    {
                        try
                        {
                            aiController.Shutdown();
                            done = true;
                        }
                        catch (CannotUnloadAppDomainException)
                        {
                            logger.Log("AppDomain Unload did not succeed. Retrying.");
                            System.Threading.Thread.Sleep(1000);
                            // keep trying to unload until it gets unloaded
                        }
                    }
                }, moduleStopped.ToString()+"-UnloadingAppDomain", logger);
                t.Start();
                t.Join(TimeSpan.FromMilliseconds(Settings.MaxFinallyBlockExecutionTime));
                if(t.IsAlive())
                    t.Abort();
            }
            else if (Constants.ModuleIsolationLevel == ModuleIsolationModes.Process)
            {
                //TODO: test this
                AddInController aiController = AddInController.GetAddInController(moduleStopped);
                aiController.Shutdown();
            }
            else if (Constants.ModuleIsolationLevel == ModuleIsolationModes.NoAddInAppDomain)
            {
                // TODO handle cleanup here
            }
            else
            {// Globals.ModuleIsolationLevel == ModuleIsolationModes.None
                // TODO handle cleanup here
            }

        }
        public void UpdateState(VModule module , VModuleState state )
        {

       //     Console.WriteLine("*** PLATFORM HAS UPDATED THE STATE of "+module.GetInfo().BinaryName()+" with secret "+module.Secret()+" to "+state.GetSimpleState());
          
            ResultCode result = new ResultCode();
            if (runningModules.ContainsKey(module)) // This will check if the module exists in runningModules AND the secrets match
            {
                lock (this)
                {
                    if (!runningModulesStates.ContainsKey(module)) // updating the first time. must be an "EnterStart" state
                    {
                        runningModulesStates[module] = state;
                    }
                    else
                    {
                        runningModulesStates[module].Update(state);
                    }
                    result = ResultCode.Success;
                }
            }
            else
            {
                result = ResultCode.ModuleNotFound;
            }


            if (result == ResultCode.Success  )
            {
          //      logger.Log(this + " updated state of module {0} to {1} ",  module.ToString(), ((ModuleState.SimpleState)state.GetSimpleState()).ToString());
            }
            else
            {
                logger.Log(this + " got invalid state update: {0} from module {1}", state.GetSimpleState().ToString(), module.ToString());
            }

        }
        /// <summary>
        /// Deregister a port to declare it unavailable for use by other modules
        /// </summary>
        /// <param name="port">The port to deregisted</param>
        /// <param name="owner">The module to which the port belongs</param>
        /// <returns></returns>
        public int DeregisterPort(VPort port, VModule module)
        {
            ResultCode result;

            lock (this)
            {
                if (registeredPorts.ContainsKey(port))
                {
                    if (module.Equals(registeredPorts[port]))
                    {
                        logger.Log("deregistering port: {0}", port.ToString());
                        registeredPorts.Remove(port);

                        result = ResultCode.Success;
                    }
                    else
                    {
                        logger.Log("got port deregisteration for {0} from a non-owner {1}", port.ToString(), module.ToString());

                        result = ResultCode.Failure;
                    }
                }
                else
                {
                    logger.Log("got deregisteration for unregistered port: {0}", port.ToString());

                    result = ResultCode.PortNotFound;
                }
            }

            if (result == ResultCode.Success)
            {
                
                BroadcastPortDeregistration(port, module); 
                // broadcast needs to be asyncronous because the module's addin (and appdomain, ports, etc) will be wiped
                /*
                System.Threading.Thread newThread = new System.Threading.Thread(delegate() { 
                 //   System.Threading.Thread.Sleep(Settings.portRegisterDelay); 
                    BroadcastPortDeregistration(port, module); });
                newThread.Name = "Deregister Port " + port;
                newThread.Start(); */
            }

            return (int)result;
        }
        /// <summary>
        /// Signals to the platform that a particular module is terminating
        /// </summary>
        /// <param name="module"></param>
        /// <returns></returns>
        public int ModuleFinished(VModule module)
        {
            ResultCode result;

            bool activePorts = ModuleHasRegisteredPorts(module);

            lock (this)
            {
                if (runningModules.ContainsKey(module) && runningModulesStates.ContainsKey(module)) // take module off platform's data structures
                {
                    //***
                    runningModules.Remove(module);
                    runningModulesStates.Remove(module);
                    //***
                    result = ResultCode.Success;
                }
                else
                {
                    logger.Log(this + "got module finished for non-existent module: {0}", module.ToString());
                    result = ResultCode.Failure;
                }
            }

            if (activePorts) // if the module has active ports deregister them
            {
                logger.Log(this + " got module finished for a module with active ports: {0}", module.ToString());
                List<VPort> portsToDeregister = new List<VPort>();
                lock (this)
                {
                    //*** Separating the parts of enumerating over registeredPorts and removing things (deregistering ports) from registeredPorts
                    foreach (VPort port in registeredPorts.Keys) // enumeration cannot continue while dictionary is being modified (e.g., dereg ports)
                    {
                        if (registeredPorts[port].Equals(module))
                        {
                            portsToDeregister.Add(port);
                        }
                    }
                }

                foreach (VPort port in portsToDeregister)
            {
                        DeregisterPort(port, module);
                }

                // we should not delete this port/service from config. we want to remember it
                //foreach (VPort port in portsToDeregister)
                //{
                //    RemovePortFromConfig(port, module);// removing ports from platform config
                //}
                    //***    
            }
            return (int)result;
        }
        /// <summary>
        /// Function call to register a port. Called by modules to activate new ports or to register changes in status.
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        public int RegisterPort(VPort port, VModule module)
        {
            ResultCode result;

            lock (this)
            {
                if (registeredPorts.ContainsKey(port))
                {
                    logger.Log(this + " got registration for an existing port: {0}", port.ToString());
                    result = ResultCode.Failure;
                }
                else
                {
                    if (runningModules.ContainsKey(module))
                    {
                        registeredPorts[port] = module;
                        logger.Log(this + " added {0} from {1}", port.ToString(), module.ToString());
                        result = ResultCode.Success;
                    }
                    else
                    {
                        logger.Log(this + " got port {0} registeration request from non-existent module {1}", port.ToString(), module.ToString());
                        result = ResultCode.ModuleNotFound;
                    }
                }
            }

            if (result == ResultCode.Success)
            {
                SafeThread newThread = new SafeThread(delegate() {
         //           System.Threading.Thread.Sleep(Settings.portRegisterDelay);
                    BroadcastPortRegistration(port, module);
                }, "RegisterPort " + port , logger);
                newThread.Start();
            }

            return (int) result;
        }