ArrayList FindHook (Hook[] hooks, HookType hookType, HookAction action, Type type, string member)
		{
			ArrayList foundHooks = new ArrayList ();
			if (hooks == null) return foundHooks;
	
			foreach (Hook hook in hooks)
			{
				if (action == HookAction.InsertBefore && (hook.InsertBefore == null || hook.InsertBefore == ""))
					continue;
				else if (action == HookAction.InsertAfter && (hook.InsertAfter == null || hook.InsertAfter == ""))
					continue;
				else if (action == HookAction.Replace && (hook.Replace == null || hook.Replace == ""))
					continue;
					
				if (hook.HookType != hookType)
					continue;
					
				if (hook.Select != null)
				{
					if (hook.Select.TypeName != null && hook.Select.TypeName != "")
						if (hook.Select.TypeName != type.FullName) continue;
		
					if (hook.Select.TypeMember != null && hook.Select.TypeMember != "")
						if (hook.Select.TypeMember != member) continue;
						
					if (hook.Select.TypeAttributes != null && hook.Select.TypeAttributes.Length > 0)
					{
						object[] ats = type.GetCustomAttributes (true);
						bool found = false;
						foreach (object at in ats)
							if (Array.IndexOf (hook.Select.TypeAttributes, at.GetType().FullName) != -1) { found = true; break; }
						if (!found) continue;
					}
				}
				foundHooks.Add (hook);
			}
			return foundHooks;
		}
예제 #2
0
		private void Worker ()
		{
			DateTime end_time_of_previous_task = DateTime.MinValue;
			double duration_of_previous_task = 0.0;

			Hook pre_hook = null;
			Hook post_hook = null;
			ArrayList to_be_executed = new ArrayList ();
			Hashtable max_priority_by_source = new Hashtable ();
			int executed_task_count = 0;
			StringBuilder status_builder = new StringBuilder ();

			while (running) {

				status_str = "Finding next task to execute";

				lock (big_lock) {

					// If there are no pending tasks, wait
					// on our lock and then re-start our
					// while loop
					if (tasks_by_tag.Count == 0) {
						if (EmptyQueueEvent != null)
							EmptyQueueEvent ();
						status_str = "Waiting on empty queue";
						Monitor.Wait (big_lock);
						executed_task_count = 0;
						continue;
					}

					if (Debug)
						Log.Debug ("Running Scheduler inner loop.  Pending tasks: {0}", tasks_by_tag.Count);

					// Walk across our list of tasks and find
					// the next one to execute.
					DateTime now = DateTime.Now;
					DateTime next_trigger_time = DateTime.MaxValue;

					// Make a first pass over our tasks, finding the
					// highest-priority item per source.
					max_priority_by_source.Clear ();
					foreach (Task task in tasks_by_tag.Values) {
						if (task.Blocked || task.TriggerTime >= now)
							continue;
						if (max_priority_by_source.Contains (task.Source)) {
							Priority p = (Priority) max_priority_by_source [task.Source];
							if (p < task.Priority)
								max_priority_by_source [task.Source] = task.Priority;
						} else {
							max_priority_by_source [task.Source] = task.Priority;
						}
					}
					
					// Now make a second pass over the tasks and find
					// the highest-priority item.  We use the information
					// from the first pass to correctly prioritize maintenance tasks.
					Task next_task = null;
					foreach (Task task in tasks_by_tag.Values) {
						if (task.Blocked)
							continue;
						if (task.TriggerTime >= now) {
							if (task.TriggerTime < next_trigger_time)
								next_trigger_time = task.TriggerTime;
							continue;
						}
						
						// If this is a maintenance task and there is a high-priority
						// task from the same source, skip it.
						if (task.Priority == Priority.Maintenance) {
							Priority p = (Priority) max_priority_by_source [task.Source];
							if (p > task.Priority)
								continue;
						}

						if (task.TriggerTime < now) {
							if (next_task == null || next_task.CompareTo (task) < 0)
								next_task = task;
						}
					}

					// If we didn't find a task, wait for the next trigger-time
					// and then re-start our while loop.
					if (next_task == null) {
						if (next_trigger_time == DateTime.MaxValue) {
							status_str = "Waiting for an unblocked task";
							Monitor.Wait (big_lock);
						} else {
							status_str = "Waiting for the next trigger time";
							Monitor.Wait (big_lock, next_trigger_time - now);
						}
						executed_task_count = 0;
						continue;
					}

					// If we did find a task, do we want to execute it right now?
					// Or should we wait a bit?

					// How should we space things out?
					double delay = 0;
					delay = ComputeDelay (next_task.Priority, duration_of_previous_task, executed_task_count);
					delay = Math.Min (delay, (next_trigger_time - now).TotalSeconds);

					if (Debug)
						Log.Debug ("Computed a delay of {0:.00}s for next task ({1}: {2})", delay, next_task.Tag, next_task.Priority);

					// Adjust by the time that has actually elapsed since the
					// last task.
					delay -= (now - end_time_of_previous_task).TotalSeconds;

					// If we still need to wait a bit longer, wait for the appropriate
					// amount of time and then re-start our while loop.
					if (delay > 0.001) {
						TimeSpan span = TimeSpanFromSeconds (delay);

						if (Debug)
							Log.Debug ("Waiting {0:.00}s until the next task at {1}", span.TotalSeconds, now + span);

						status_str = String.Format ("Waiting for next task at {0}", now + span);
						Monitor.Wait (big_lock, span);
						executed_task_count = 0;
						continue;
					}

					//
					// If we've made it to this point, it is time to start
					// executing our selected task.
					//

					to_be_executed.Clear ();

					if (next_task.Collector == null) {

						to_be_executed.Add (next_task);

					} else {

						pre_hook = new Hook (next_task.Collector.PreTaskHook);
						post_hook = new Hook (next_task.Collector.PostTaskHook);

						// Find all eligible tasks with the same collector,
						// and add them to the collection list.
						now = DateTime.Now;
						foreach (Task task in tasks_by_tag.Values)
							if (task != next_task
							    && task.Collector == next_task.Collector
							    && !task.Blocked
							    && task.TriggerTime < now)
								to_be_executed.Add (task);

						// Order the tasks from highest to lowest priority.
						// Our original task will always be the first item
						// in the resulting array.
						to_be_executed.Sort ();
						to_be_executed.Add (next_task);
						to_be_executed.Reverse ();

						// Now find how many tasks can be executed before we
						// exceed the collector's maximum weight.  If necessary,
						// prune the list of tasks.
						double remaining_weight;
						remaining_weight = next_task.Collector.GetMaximumWeight ();
						int i = 0;
						while (i < to_be_executed.Count && remaining_weight > 0) {
							Task task;
							task = to_be_executed [i] as Task;
							remaining_weight -= task.Weight;
							++i;
						}
						if (i < to_be_executed.Count)
							to_be_executed.RemoveRange (i, to_be_executed.Count - i);
					}

					// Remove the tasks we are about to execute from our 
					// master list.
					foreach (Task task in to_be_executed)
						tasks_by_tag.Remove (task.Tag);

					// Pulse our lock, in case anyone is waiting for it.
					Monitor.Pulse (big_lock);
				}

				// Now actually execute the set of tasks we found.

				status_builder.Length = 0;
				status_builder.Append ("Executing task");
				if (to_be_executed.Count > 1)
					status_builder.Append ('s');
				status_builder.Append ('\n');
				foreach (Task task in to_be_executed) {
					task.AppendToStringBuilder (status_builder);
					status_builder.Append ('\n');
				}
				status_str = status_builder.ToString ();

				DateTime start_time = DateTime.Now;
				if (pre_hook != null) {
					try {
						pre_hook ();
					} catch (Exception ex) {
						Logger.Log.Error (ex, "Caught exception in pre_hook '{0}'", pre_hook);
					}
				}
				foreach (Task task in to_be_executed) {
					task.DoTask ();
					++total_executed_task_count;
					++executed_task_count;
				}
				if (post_hook != null) {
					try {
						post_hook ();
					} catch (Exception ex) {
						Logger.Log.Error (ex, "Caught exception in post_hook '{0}'", post_hook);
					}
				}

				end_time_of_previous_task = DateTime.Now;
				duration_of_previous_task = (end_time_of_previous_task - start_time).TotalSeconds;
			}

			// Execute all shutdown tasks
			foreach (Task task in shutdown_task_queue)
				if (! task.Cancelled && ! task.Blocked)
					task.DoTask ();

			// Call Cleanup on all of our unexecuted tasks
			foreach (Task task in tasks_by_tag.Values)
				task.Cleanup ();

			if (Debug)
				Logger.Log.Debug ("Scheduler.Worker finished");
		}
예제 #3
0
			public TaskGroupPrivate (string name,
						 Hook   pre_hook,
						 Hook   post_hook)
			{
				this.name = name;
				this.pre_hook = pre_hook;
				this.post_hook = post_hook;
			}
예제 #4
0
		//////////////////////////////////////////////////////////////////////////////

		//
		// Task Groups
		//

		public static TaskGroup NewTaskGroup (string name, Hook pre_hook, Hook post_hook)
		{
			return new TaskGroupPrivate (name, pre_hook, post_hook);
		}