]> git.mxchange.org Git - hub.git/blob - application/hub/main/handler/tasks/class_TaskHandler.php
Exceptions/interfaces/classes added:
[hub.git] / application / hub / main / handler / tasks / class_TaskHandler.php
1 <?php
2 /**
3  * A Task handler
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 Hub Developer Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24 class TaskHandler extends BaseHandler implements Registerable, HandleableTask {
25         // Exception constants
26         const EXCEPTION_TASK_IS_INVALID = 0xb00;
27
28         /**
29          * A task list instance
30          */
31         private $listInstance = null;
32
33         /**
34          * Instance for iterator
35          */
36         private $iteratorInstance = null;
37
38         /**
39          * Visitor instance for all tasks while they are active
40          */
41         private $visitorInstance = null;
42
43         /**
44          * Protected constructor
45          *
46          * @return      void
47          */
48         protected function __construct () {
49                 // Call parent constructor
50                 parent::__construct(__CLASS__);
51
52                 // Init the task list
53                 $this->listInstance = ObjectFactory::createObjectByConfiguredName('task_list_class');
54
55                 // Get default instance
56                 $this->iteratorInstance = $this->listInstance->getIterator();
57
58                 // Init visitor instance for faster loop
59                 $this->visitorInstance = ObjectFactory::createObjectByConfiguredName('active_task_visitor_class');
60         }
61
62         /**
63          * Creates an instance of this class
64          *
65          * @return      $handlerInstance        An instance of a HandleableTask class
66          */
67         public final static function createTaskHandler () {
68                 // Get new instance
69                 $handlerInstance = new TaskHandler();
70
71                 // Output debug message
72                 $handlerInstance->debugOutput('TASK-HANDLER: Task handler initialized.');
73
74                 // Return the prepared instance
75                 return $handlerInstance;
76         }
77
78         /**
79          * Tries to execute the given task. If as task should not be started (yet)
80          * or the interval time (see task_interval_delay) is not yet reached the
81          * task is quietly skipped.
82          *
83          * @return      void
84          * @throws      InvalidTaskException    If the current task is invalid
85          */
86         private function executeCurrentTask () {
87                 // Update no task by default
88                 $updateTask = false;
89
90                 // Is the current task valid?
91                 if (!$this->iteratorInstance->valid()) {
92                         // Not valid!
93                         throw new InvalidTaskException($this, self::EXCEPTION_TASK_IS_INVALID);
94                 } // END - if
95
96                 // Get current task
97                 $currentTask = $this->iteratorInstance->current();
98
99                 // Is the task not yet started?
100                 if ($currentTask['task_started'] === false) {
101                         // Determine difference between current time and registration
102                         $diff = ($this->getMilliTime() - $currentTask['task_registered']) * 1000;
103
104                         // Should we start now?
105                         if ($diff < $currentTask['task_startup_delay']) {
106                                 // Skip this silently
107                                 return false;
108                         } // END - if
109
110                         // Launch the task and mark it as updated
111                         $currentTask['task_started'] = true;
112                         $updateTask = true;
113                 } // END - if
114
115                 // Get time difference from interval delay
116                 $diff = ($this->getMilliTime() - $currentTask['task_last_activity']) * 1000;
117
118                 // Is the interval delay reached?
119                 if ($diff < $currentTask['task_interval_delay']) {
120                         // Should we update the task from startup?
121                         if ($updateTask === true) {
122                                 // Update the task before leaving
123                                 $this->updateTask($currentTask);
124                         } // END - if
125
126                         // Skip this silently
127                         return false;
128                 } // END - if
129
130                 // Set last activity
131                 $currentTask['task_last_activity'] = $this->getMilliTime();
132
133                 // Update the task
134                 $this->updateTask($currentTask);
135
136                 // And visit/run it
137                 // @TODO Messurement can be added around this call
138                 $currentTask['task_instance']->accept($this->visitorInstance);
139         }
140
141         /**
142          * Updates given task by updating the underlaying list
143          *
144          * @param       $taskEntry      An array with a task
145          * @return      void
146          */
147         private function updateTask (array $taskEntry) {
148                 // Get the key from current iteration
149                 $key = $this->iteratorInstance->key();
150
151                 // Get the hash from key
152                 $hash = $this->listInstance->getHash($key);
153
154                 // Update the entry
155                 $this->listInstance->updateCurrentEntryByHash($hash, $taskEntry);
156         }
157
158         /**
159          * Registers a task with a task handler.
160          *
161          * @param       $taskName               A task name to register the task on
162          * @param       $taskInstance   The instance we should register as a task
163          * @return      void
164          */
165         public function registerTask ($taskName, Visitable $taskInstance) {
166                 // Create the entry
167                 $taskEntry = array(
168                         // Identifier for the generateHash() method
169                         'id'                  => $taskName,
170                         // Wether the task is started
171                         'task_started'        => false,
172                         // Wether the task is paused (not yet implemented)
173                         'task_paused'         => false,
174                         // Wether the task can be paused (not yet implemented)
175                         'task_pauseable'      => true,
176                         // Timestamp of registration
177                         'task_registered'     => $this->getMilliTime(),
178                         // Last activity timestamp
179                         'task_last_activity'  => 0,
180                         // Task instance itself
181                         'task_instance'       => $taskInstance,
182                         // Startup delay in milliseconds
183                         'task_startup_delay'  => $this->getConfigInstance()->getConfigEntry('task_' . $taskName . '_startup_delay'),
184                         // Interval time (delay) in milliseconds before this task is executed again
185                         'task_interval_delay' => $this->getConfigInstance()->getConfigEntry('task_' . $taskName . '_interval_delay'),
186                 );
187
188                 // Add the entry
189                 $this->listInstance->addEntry('tasks', $taskEntry);
190
191                 // Debug message
192                 $this->debugOutput('TASK-HANDLER: Task ' . $taskName .
193                         ' (taskInstance=' . $taskInstance->__toString() . ')' .
194                         ', startupDelay=' . $taskEntry['task_startup_delay'] . 'ms' .
195                         ', intervalDelay=' . $taskEntry['task_interval_delay'] . 'ms registered.'
196                 );
197         }
198
199         /**
200          * Checks wether tasks are left including idle task
201          *
202          * @return      $tasksLeft      Wether there are tasks left to handle
203          */
204         public function hasTasksLeft () {
205                 // Do we have tasks there?
206                 $tasksLeft = (($this->listInstance instanceof Listable) && ($this->listInstance->count() > 0));
207
208                 // Return result
209                 return $tasksLeft;
210         }
211
212         /**
213          * Handles all tasks by checking if they should startup or if it is their
214          * turn to run. You should use this method in a while() loop in conjuntion
215          * with hasTasksLeft() so you can e.g. shutdown by adding a ShutdownTask
216          * which will attempt to remove all tasks from the task handler.
217          *
218          * @return      void
219          */
220         public function handleTasks () {
221                 // Should we rewind?
222                 if (!$this->iteratorInstance->valid()) {
223                         // Rewind to the beginning for next loop
224                         $this->iteratorInstance->rewind();
225                 } // END - if
226
227                 // Try to execute the task
228                 $this->executeCurrentTask();
229
230                 // Go to next entry
231                 $this->iteratorInstance->next();
232         }
233 }
234
235 // [EOF]
236 ?>