/// <summary> /// Execute a thread on a dedicated Executor. /// /// Right before the execution the thread's status is set the Scheduled /// and the thread's executor is set to the executor's ID. /// Spawn a new thread that remotes the execution to the Executor. /// /// </summary> /// <param name="ds">Containes the Thread ID and the Executor ID.</param> /// <returns>True if the thread was successfully started on the Executor.</returns> public bool ExecuteThread(DedicatedSchedule ds) { bool success = false; MThread mt = new MThread(ds.TI); try { /// [email protected] - Feb 28, 2006: /// moved the thread status updating here from ManagerContainer.StartDispatch /// to make sure that the thread state is written in the right order mt.CurrentExecutorId = ds.ExecutorId; mt.State = ThreadState.Scheduled; logger.Debug(String.Format("Dispatching thread {0} to executor: {1}", ds.TI.ThreadId, ds.ExecutorId)); // [email protected] - Jul 17, 2006: changed to parameterized thread start. ExecuteCurrentThreadParameters oParameters = new ExecuteCurrentThreadParameters(ds.TI, mt); Thread dispatchThread = new Thread(new ParameterizedThreadStart(this.ExecuteCurrentThread)); dispatchThread.Name = "ScheduleDispatchThread"; dispatchThread.Start(oParameters); success = true; } catch (Exception ex) { // restore the thread status so another executor can pick it up mt.CurrentExecutorId = null; mt.State = ThreadState.Ready; logger.Debug("Error scheduling thread on executor " + _Id, ex); } return(success); }
/// <summary> /// Execute a thread on a dedicated Executor. /// /// Right before the execution the thread's status is set the Scheduled /// and the thread's executor is set to the executor's ID. /// Spawn a new thread that remotes the execution to the Executor. /// /// </summary> /// <param name="ds">Containes the Thread ID and the Executor ID.</param> /// <returns>True if the thread was successfully started on the Executor.</returns> public bool ExecuteThread(DedicatedSchedule ds) { bool success = false; //kna added this to allow controlling MAX_CONCURRENT_THREADS per executor. Aug19. 05 //find # of executing threads from the db. int numConcurrentThreads = 0; MThread mt = new MThread(ds.TI); try { numConcurrentThreads = ManagerStorageFactory.ManagerStorage().GetExecutorThreadCount( _Id, ThreadState.Ready, ThreadState.Scheduled, ThreadState.Started); if (numConcurrentThreads >= MAX_CONCURRENT_THREADS) { success = false; } else { /// [email protected] - Feb 28, 2006: /// moved the thread status updating here from ManagerContainer.ScheduleDedicated /// to make sure that the thread state is written in the right order mt.CurrentExecutorId = ds.ExecutorId; mt.State = ThreadState.Scheduled; logger.Debug(String.Format("Scheduling thread {0} to executor: {1}", ds.TI.ThreadId, ds.ExecutorId)); this.currentTI = ds.TI; Thread dispatchThread = new Thread(new ThreadStart(this.ExecuteCurrentThread)); dispatchThread.Name = "ScheduleDispatchThread"; dispatchThread.Start(); success = true; } } catch (Exception ex) { // restore the thread status so another executor can pick it up mt.CurrentExecutorId = null; mt.State = ThreadState.Ready; logger.Debug("Error scheduling thread on executor " + _Id, ex); } return(success); }
private void StartDispatch() { logger.Info("Dispatcher thread started."); try { // TODO: allow scheduling of multiple threads in one go while (!_stop) { try { //logger.Debug("WaitOne for 1000 millis on DedicatedSchedulerActive"); InternalShared.Instance.DedicatedSchedulerActive.WaitOne(1000, false); //logger.Debug("Getting a dedicated schedule"); DedicatedSchedule ds = InternalShared.Instance.Scheduler.ScheduleDedicated(); if (ds == null) { //to avoid blocking again if stop has been called. if (!_stop) { InternalShared.Instance.DedicatedSchedulerActive.Reset(); //logger.Debug("Dedicated schedule is null. Reset the DedicatedSchedulerActive waithandle"); } } else { logger.Debug(String.Format("Scheduler mapped thread {0} to executor: {1}", ds.TI.ThreadId, ds.ExecutorId)); MExecutor me = new MExecutor(ds.ExecutorId); try { // dispatch thread me.ExecuteThread(ds); /// [email protected] - Feb 28, 2006: /// updating the thread's status is done inside ExecuteThread after it was decided /// whether this executor can take it or not /// this prevents race conditions if the Executor finishes very quickly /// and we overwrite here the Executor's status back to Scheduled after it was finished // // update thread state 'after' it is dispatched. (kna changed this: aug19,05). to prevent the scheduler from hanging here. // mt.CurrentExecutorId = ds.ExecutorId; // mt.State = ThreadState.Scheduled; // logger.Debug("Scheduled thread " + ds.TI.ThreadId + " to executor:"+ds.ExecutorId); } catch (Exception e) { logger.Error("Some error occured trying to schedule. Reset-ing the thread to be scheduled. Continuing...", e); MThread mt = new MThread(ds.TI); mt.Reset(); // this should happen as part of the disconnection } } } catch (ThreadAbortException) { logger.Debug("Dispatcher Thread resetting abort (1)..."); Thread.ResetAbort(); } catch (Exception e) { if (e is DbException) { //some problem contacting database //wait for a bit and try again logger.Debug("Error contacting database:", e); Thread.Sleep(30000); //TODO: need to provide fault tolerance here: what if the database/storage cannot be contacted.? //TODO: in that case, just raise an event, and let the Service/exec deal with it. } else { logger.Error("Dispatch thread error. Continuing...", e); } } } //while } catch (ThreadAbortException) { logger.Debug("Scheduler Thread resetting abort (2)..."); Thread.ResetAbort(); } catch (Exception e) { logger.Error("StartDispatch thread error. Scheduler thread stopped.", e); } logger.Info("Scheduler thread exited."); }
//----------------------------------------------------------------------------------------------- /// <summary> /// Gets the identifier of the next scheduled thread. /// </summary> /// <param name="sc">security credentials to verify if the executor has permission to perform this operation /// (i.e GetNextScheduledThreadIdentifier, which is associated with the ExecuteThread permission)</param> /// <param name="executorId">executor id</param> /// <returns>ThreadIdentifier object representing the next scheduled grid thread</returns> public ThreadIdentifier Executor_GetNextScheduledThreadIdentifier(SecurityCredentials sc, string executorId) { AuthenticateUser(sc); EnsurePermission(sc, Permission.ExecuteThread); bool scheduled = false; ThreadIdentifier ti; // critical section .. don't want to schedule same thread on multiple executors Monitor.Enter(InternalShared.Instance); //logger.Debug("Entering monitor..."); // try and get a local thread ti = InternalShared.Instance.Scheduler.ScheduleNonDedicated(executorId); if (ti != null) { //logger.Debug("Schedule-non-dedicated gave Ti:"+ti.ThreadId); scheduled = true; } else { // no thread, so can release lock immediately Monitor.Exit(InternalShared.Instance); //logger.Debug("No thread. so releasing lock immediately."); } // TODO: hierarchical grids ignored until after v1.0.0 /* else if ((ti == null) & (Manager != null)) { // no local threads .. request thread from next manager and "simulate" the fact that it was scheduled locally ti = Manager.Executor_GetNextScheduledThreadIdentifier(null, _Id); if (ti != null) { scheduled = true; MThread t = new MThread(ti); t.Init(false); t.Priority = ti.Priority + 1; } } */ if (scheduled) { logger.Debug("obtained thread..."+ti.ThreadId); MThread t = new MThread(ti); t.State = ThreadState.Scheduled; t.CurrentExecutorId = executorId; // finished scheduling thread, can release lock Monitor.Exit(InternalShared.Instance); logger.Debug("set state of thread to scheduled. set executorID for the thread. released lock"); } return ti; }
/// <summary> /// Constructor that takes the thread identifier and mthread. /// </summary> /// <param name="oThreadIdentifier">thread identifier parameter</param> /// <param name="oMThread">mthread parameter</param> public ExecuteCurrentThreadParameters(ThreadIdentifier oThreadIdentifier, MThread oMThread) { _ThreadIdentifier = oThreadIdentifier; _MThread = oMThread; }
/// <summary> /// Execute a thread on a dedicated Executor. /// /// Right before the execution the thread's status is set the Scheduled /// and the thread's executor is set to the executor's ID. /// Spawn a new thread that remotes the execution to the Executor. /// /// </summary> /// <param name="ds">Containes the Thread ID and the Executor ID.</param> /// <returns>True if the thread was successfully started on the Executor.</returns> public bool ExecuteThread(DedicatedSchedule ds) { bool success = false; //kna added this to allow controlling MAX_CONCURRENT_THREADS per executor. Aug19. 05 //find # of executing threads from the db. int numConcurrentThreads = 0; MThread mt = new MThread(ds.TI); try { numConcurrentThreads = ManagerStorageFactory.ManagerStorage().GetExecutorThreadCount( _Id, ThreadState.Ready, ThreadState.Scheduled, ThreadState.Started); if (numConcurrentThreads >= MAX_CONCURRENT_THREADS) { success = false; } else { /// [email protected] - Feb 28, 2006: /// moved the thread status updating here from ManagerContainer.ScheduleDedicated /// to make sure that the thread state is written in the right order mt.CurrentExecutorId = ds.ExecutorId; mt.State = ThreadState.Scheduled; logger.Debug(String.Format("Scheduling thread {0} to executor: {1}", ds.TI.ThreadId, ds.ExecutorId)); this.currentTI = ds.TI; Thread dispatchThread = new Thread(new ThreadStart(this.ExecuteCurrentThread)); dispatchThread.Name = "ScheduleDispatchThread"; dispatchThread.Start(); success = true; } } catch (Exception ex) { // restore the thread status so another executor can pick it up mt.CurrentExecutorId = null; mt.State = ThreadState.Ready; logger.Debug("Error scheduling thread on executor "+ _Id, ex); } return success; }