1 <?php
2 /*
3 This code is part of GOsa (https://gosa.gonicus.de)
4 Copyright (C) 2007 Fabian Hickert
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
22 /*!
23 \brief This class represents the host action queue.
24 \author Fabian Hickert <hickert@gonicus.de>
25 \version 2.6
26 \date 24.10.2007
28 This class is a queue handler, which allows adding,removing,
29 priority settings,stop and resume actions... for each queue entry
30 */
31 class hostActionQueue {
33 private $o_config = NULL;
34 private $s_queue_file = "";
35 private $s_error = "";
36 private $b_error = FALSE;
38 private $a_queue = array();
39 private $i_pointer = 0;
40 private $b_queue_loaded = false;
41 private $i_fileversion = 0;
43 private $id_entry_map = array();
45 public function __construct($config)
46 {
47 $this->o_config= $config;
49 /* Define source file */
50 $this->s_queue_file = CONFIG_DIR."/gotomasses_machines";
52 $file = $this->o_config->search("gotomasses", "STORAGE_FILE",array('menu'));
53 if(!empty($file)){
54 $this->s_queue_file = $file;
55 }
56 }
58 private function _reload_queue()
59 {
60 $this->_reset_error();
61 $this->b_queue_loaded = FALSE;
62 $this->b_error = FALSE;
63 $this->s_error = "";
64 $this->i_pointer = 0;
66 /* Check file accessibility */
67 if(!file_exists($this->s_queue_file)){
68 $this->set_error(sprintf(_("Can't locate gotomasses queue file '%s'."),$this->s_queue_file));
69 return(FALSE);
70 }
71 if(!is_readable($this->s_queue_file)){
72 $this->set_error(sprintf(_("Can't read gotomasses queue file '%s'."),$this->s_queue_file));
73 return(FALSE);
74 }
76 /* Check if file contents could be read */
77 $fp = @fopen($this->s_queue_file,"r");
78 if(!$fp){
79 $this->set_error(sprintf(_("Can't read gotomasses storage file '%s'."),$this->s_queue_file));
80 return(FALSE);
81 }
82 $this->i_fileversion = filemtime($this->s_queue_file);
83 clearstatcache();
85 /* Get file contents */
86 $data ="";
87 while(!feof($fp)){
88 $data.= fread($fp,512);
89 }
91 /* Get lines from file */
92 $this->a_queue = array();
93 $comment = "";
94 $rows = split("\n",$data);
96 $used_ids = array();
98 /* Walk trough rows and parse data */
99 foreach($rows as $row){
101 /* Skip empty lines */
102 $row = trim($row);
103 if(empty($row)){
104 continue;
105 }
107 /* Get comment, if available */
108 if(preg_match("/^#/",$row)){
109 $comment = preg_replace("/^#/","",$row);
110 continue;
111 }
113 $entry_id = $task_id= "";
115 /* Comment must be set correctly */
116 if(empty($comment)){
117 $desc = "";
118 }else{
119 $task_id =preg_replace("/^.*taskid:([0-9a-z]*).*$/i","\\1",$comment);
120 $entry_id=preg_replace("/^.*entryid:([0-9a-z]*).*$/i","\\1",$comment);
121 $desc =preg_replace("/^.*desc:(.*)$/","\\1",$comment);
122 }
123 if($task_id == "" || empty($task_id)){
124 $task_id = $this->get_new_id();
125 }
126 if($entry_id == "" || empty($entry_id)){
127 $entry_id = $this->get_new_id();
128 }
130 /* Get unige id */
131 while(in_array($entry_id,$used_ids)){
132 $entry_id = $this->get_new_id();
133 }
134 $used_ids[] = $entry_id;
136 /* Split row into minutes/ hours ...*/
137 $row = preg_replace('/[\t ]/umi'," ",$row);
138 $row = preg_replace('/ */umi'," ",$row);
139 $parts = split(" ",$row);
141 if(count($parts) != 10){
142 print_red(_("Entry broken, skipped."));
143 }else{
145 $entry = array();
146 $entry['TASK_ID'] = $task_id;
147 $entry['ID'] = $entry_id;
148 $entry['Minute'] = $parts[0];
149 $entry['Hour'] = $parts[1];
150 $entry['Day'] = $parts[2];
151 $entry['Month'] = $parts[3];
152 $entry['Weekday'] = $parts[4];
153 $entry['Action'] = $parts[5];
154 $entry['OGroup'] = $parts[6];
155 $entry['Zone'] = $parts[7];
156 $entry['Section'] = $parts[8];
157 if($entry['Action'] == "initial_install"){
158 $tmp2 = split(";",$parts[9]);
159 foreach($tmp2 as $target){
160 $tmp = split(",",$target);
161 $entry['Initial_Target'][] = array(
162 "MAC" => $tmp[0],
163 "IP" => $tmp[1],
164 "NAME" => $tmp[2]);
165 }
166 $entry['Target'] = array();
167 }else{
168 $entry['Initial_Target'] = array();
169 $entry['Target'] = split(";",$parts[9]);
170 }
171 $entry['Comment'] = $desc;
172 $this->a_queue[] = $entry;
173 }
174 $comment = "";
175 }
177 /* Udpate ENTRY_ID -> id mapping */
178 reset($this->a_queue);
179 foreach($this->a_queue as $id => $entry){
180 $this->id_entry_map[$entry['ID']] = $id;
181 }
183 return(TRUE);
184 }
187 private function _save_data()
188 {
189 $this->_reset_error();
191 /* Check file accessibility */
192 if(!file_exists($this->s_queue_file)){
193 $this->set_error(sprintf(_("Can't locate gotomasses queue file '%s'."),$this->s_queue_file));
194 return(FALSE);
195 }
196 if(!is_writeable($this->s_queue_file)){
197 $this->set_error(sprintf(_("Can't write gotomasses queue file '%s'."),$this->s_queue_file));
198 return(FALSE);
199 }
200 if($this->i_fileversion != filemtime($this->s_queue_file)){
201 $this->set_error(_("The queue file was modified since last reload. Can't save changes."));
202 return(FALSE);
203 }
204 $fp = @fopen($this->s_queue_file,"w");
205 if(!$fp){
206 $this->set_error(sprintf(_("Can't write gotomasses queue file '%s'."),$this->s_queue_file));
207 return(FALSE);
208 }
210 $str = "#GOsa generated file, please just modify if you really know what you do.";
211 reset($this->a_queue);
212 foreach($this->a_queue as $task){
213 $str .= "\n#taskid:".trim($task['TASK_ID']).";entryid:".$task['ID'].";desc:".trim($task['Comment']);
214 $str .= "\n";
215 if($task['Action'] == "initial_install"){
216 $str .= "* * * * * ";
217 }else{
218 $str .= str_pad($task['Minute'] ,5," ")." ";
219 $str .= str_pad($task['Hour'] ,5," ")." ";
220 $str .= str_pad($task['Day'] ,5," ")." ";
221 $str .= str_pad($task['Month'] ,5," ")." ";
222 $str .= str_pad($task['Weekday'],5," ")." ";
223 }
224 $str .= str_pad($task['Action'] ,5," ")." ";
225 $str .= str_pad($task['OGroup'] ,5," ")." ";
226 $str .= str_pad($task['Zone'] ,5," ")." ";
227 $str .= str_pad($task['Section'],5," ")." ";
228 if($task['Action'] == "initial_install"){
229 foreach($task['Initial_Target'] as $target){
230 $str .= trim($target['MAC']).",".trim($target['IP']).",".trim($target['NAME']).";";
231 }
232 }else{
233 foreach($task['Target'] as $target){
234 $str .= $target.";";
235 }
236 }
237 $str = preg_replace("/;$/","",$str);
238 }
240 /* Write contents */
241 $str .= "\n";
242 fwrite($fp,$str);
243 fclose($fp);
244 clearstatcache();
245 $this->i_fileversion = filemtime($this->s_queue_file);
246 clearstatcache();
248 /* Update ENTRY_ID -> id mapping */
249 reset($this->a_queue);
250 foreach($this->a_queue as $id => $entry){
251 $this->id_entry_map[$entry['ID']] = $id;
252 }
254 return(TRUE);
255 }
257 private function _add_entry($entry,$task_id = "")
258 {
259 if($task_id == "" || empty($task_id)){
260 $task_id = $this->get_new_id();
261 }
262 $entry['TASK_ID'] = $task_id;
263 if(!isset($entry['ID']) || empty($entry['ID']) || !isset($entry['ID']) || empty($entry['ID'])){
264 $entry['ID'] = $this->get_new_id();
265 }
266 $this->a_queue[] = $entry;
268 return(true);
269 }
271 public function get_entry($id)
272 {
273 if(isset($this->a_queue[$this->id_entry_map[$id]])){
274 return($this->a_queue[$this->id_entry_map[$id]]);
275 }else{
276 $this->set_error(sprintf(_("Entry with id '%s' not found."),$id));
277 }
278 }
280 public function update_entry($id,$entry)
281 {
282 if(isset($this->id_entry_map[$id])){
283 $this->a_queue[$this->id_entry_map[$id]] = $entry;
284 return($this->_save_data());
285 }else{
286 $this->set_error(sprintf(_("Could not update entry, entry with id '%s' not found."),$id));
287 }
288 }
290 public function remove_entry($id)
291 {
292 if(isset($this->id_entry_map[$id])){
293 unset($this->a_queue[$this->id_entry_map[$id]]);
294 unset($this->id_entry_map[$id]);
295 return($this->_save_data());
296 }else{
297 $this->set_error(sprintf(_("Could not remove entry, entry with id '%s' not found."),$id));
298 }
299 }
301 public function id_exists($id)
302 {
303 return(isset($this->id_entry_map[$id]));
304 }
307 public function add($entry)
308 {
309 if(!$this->_add_entry($entry)){
310 return(FALSE);
311 }
312 return($this->_save_data());
313 }
315 public function add_multiple($array)
316 {
317 $task_id = $this->get_new_id();
318 foreach($array as $entry){
319 if(!$this->_add_entry($entry,$task_id)){
320 return(FALSE);
321 }
322 }
323 return($this->_save_data());
324 }
326 public function fetch()
327 {
328 if(isset($this->a_queue[$this->i_pointer])){
329 $p = $this->a_queue[$this->i_pointer];
330 $this->i_pointer ++;
331 return($p);
332 }
333 return(FALSE);
334 }
336 public function load()
337 {
338 return($this->_reload_queue());
339 }
341 public function save()
342 {
343 return($this->_save_data());
344 }
346 private function _reset_error()
347 {
348 $this->b_error = FALSE;
349 $this->s_error = "";
350 }
352 private function set_error($str)
353 {
354 $this->b_error = TRUE;
355 $this->s_error = $str;
356 }
358 public function is_error()
359 {
360 return($this->b_error);
361 }
363 public function get_error()
364 {
365 return($this->s_error);
366 }
368 public function max_entry_priority($id)
369 {
370 if(!$this->id_exists($id)){
371 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
372 return(FALSE);
373 }
374 $tmp = array();
375 $tmp[]= $this->get_entry($id);
376 reset($this->a_queue);
377 foreach($this->a_queue as $key => $entry){
378 if($id != $entry['ID']){
379 $tmp[] = $entry;
380 }
381 }
382 $this->a_queue=$tmp;
383 return($this->_save_data());
384 }
386 public function increase_entry_priority($id)
387 {
388 if(!$this->id_exists($id)){
389 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
390 return(FALSE);
391 }
392 $tmp = array();
393 $skip = NULL;
394 $next = NULL;
395 reset($this->a_queue);
396 foreach($this->a_queue as $key => $entry){
397 if($next != NULL){
398 if($id == $entry['ID']){
399 $tmp[] = $entry;
400 $tmp[] = $next;
401 $next = NULL;
402 }else{
403 $tmp[] = $next;
404 $next = $entry;
405 }
406 }else{
407 $next = $entry;
408 }
409 }
410 if($next != NULL){
411 $tmp[] = $next;
412 }
413 $this->a_queue=$tmp;
414 return($this->_save_data());
415 }
417 public function decrease_entry_priority($id)
418 {
419 if(!$this->id_exists($id)){
420 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
421 return(FALSE);
422 }
423 $tmp = array();
424 $skip = NULL;
425 reset($this->a_queue);
426 foreach($this->a_queue as $key => $entry){
427 if($id != $entry['ID']){
428 $tmp[] = $entry;
429 if($skip != NULL){
430 $tmp[] = $skip;
431 $skip = NULL;
432 }
433 }else{
434 $skip = $entry;
435 }
436 }
437 if($skip != NULL){
438 $tmp[] = $skip;
439 }
440 $this->a_queue=$tmp;
441 return($this->_save_data());
442 }
444 private function get_new_id()
445 {
446 $mt = microtime();
447 $sec = preg_replace("/^0.([0-9]*) ([0-9]*)$/","\\2",$mt);
448 $msec = preg_replace("/^0.([0-9]*) ([0-9]*)$/","\\1",$mt);
449 return(strtoupper(base_convert($sec,10,36).base_convert($msec,10,36)));
450 }
452 public function min_entry_priority($id)
453 {
454 if(!$this->id_exists($id)){
455 $this->set_error(sprintf(_("Can't set priority for ID '%s'. ID does not exist."),$id));
456 return(FALSE);
457 }
458 reset($this->a_queue);
459 $tmp = array();
460 foreach($this->a_queue as $key => $entry){
461 if($id != $entry['ID']){
462 $tmp[] = $entry;
463 }
464 }
465 $tmp[]= $this->get_entry($id);
466 $this->a_queue=$tmp;
467 return($this->_save_data());
468 }
469 }
470 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
471 ?>