Add Whentools library, test, documentation.
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 23 Feb 2012 15:07:23 +0000 (15:07 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 23 Feb 2012 16:08:09 +0000 (16:08 +0000)
14 files changed:
daemon/whenjobsd.ml
lib/Makefile.am
lib/whenfile.ml
lib/whenfile.mli
lib/whentools.ml [new file with mode: 0644]
lib/whentools.mli [new file with mode: 0644]
tests/jobs/Makefile.am
tests/jobs/t200_ocaml_jobnames.ml [new file with mode: 0644]
tests/jobs/t200_ocaml_jobnames.ml.expected [new file with mode: 0644]
tests/jobs/t201_ocaml_set_variable.ml [new file with mode: 0644]
tests/jobs/t201_ocaml_set_variable.ml.expected [new file with mode: 0644]
tests/parsing/test_load.ml
tools/whenjobs.ml
tools/whenjobs.pod

index 3f9fe89..164a7e2 100644 (file)
@@ -19,6 +19,9 @@
 open Unix
 open Printf
 
+(* Ensures that Whentools module is linked to the daemon. *)
+let _ = Whentools.set_variable
+
 let () =
   (* Running the daemon as root is a mistake.  It must be run as a
    * non-root user.
index 61d0ad6..76a2d26 100644 (file)
@@ -39,6 +39,8 @@ SOURCES = \
        whenproto_aux.mli \
        whenstate.ml \
        whenstate.mli \
+       whentools.ml \
+       whentools.mli \
        whenutils.ml \
        whenutils.mli
 
@@ -50,6 +52,7 @@ CMI_FILES = \
        whenlock.cmi \
        whenproto_aux.cmi \
        whenstate.cmi \
+       whentools.cmi \
        whenutils.cmi
 
 # In dependency order.
@@ -60,6 +63,7 @@ OBJECTS = \
        whenexpr.cmo \
        whenstate.cmo \
        whenfile.cmo \
+       whentools.cmo \
        whenlock.cmo
 
 # Library.
index b109e66..1617c29 100644 (file)
@@ -36,4 +36,7 @@ let add_every_job _loc name e sh =
               job_cond = Every_job e; job_script = sh } in
   state := Whenstate.add_job !state job
 
+let set_variable name value =
+  state := Whenstate.set_variable !state name value
+
 let get_state () = !state
index 54ee52d..a66f865 100644 (file)
@@ -48,3 +48,6 @@ val add_every_job : Camlp4.PreCast.Loc.t -> string -> Whenexpr.periodexpr -> Whe
     [periodexpr] is the period, eg. 30 seconds.
 
     [sh] is the shell script fragment. *)
+
+val set_variable : string -> Whenexpr.variable -> unit
+(** Set a variable during file load. *)
diff --git a/lib/whentools.ml b/lib/whentools.ml
new file mode 100644 (file)
index 0000000..979124f
--- /dev/null
@@ -0,0 +1,38 @@
+(* whenjobs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Big_int
+open Whenexpr
+
+let set_variable name value =
+  check_valid_variable_name name;
+  Whenfile.set_variable name (T_string value)
+
+let set_variable_bool name value =
+  check_valid_variable_name name;
+  Whenfile.set_variable name (T_bool value)
+
+let set_variable_int name value =
+  check_valid_variable_name name;
+  Whenfile.set_variable name (T_int (big_int_of_int value))
+
+let set_variable_string = set_variable
+
+let set_variable_float name value =
+  check_valid_variable_name name;
+  Whenfile.set_variable name (T_float value)
diff --git a/lib/whentools.mli b/lib/whentools.mli
new file mode 100644 (file)
index 0000000..8dd88cd
--- /dev/null
@@ -0,0 +1,35 @@
+(* whenjobs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(** [Whentools] contains helper functions that jobs can call as they
+    are loading. *)
+
+val set_variable : string -> string -> unit
+(** Set variable (just a wrapper around {!Whenfile.set_variable}). *)
+
+val set_variable_bool : string -> bool -> unit
+(** Set variable (just a wrapper around {!Whenfile.set_variable}). *)
+
+val set_variable_int : string -> int -> unit
+(** Set variable (just a wrapper around {!Whenfile.set_variable}). *)
+
+val set_variable_string : string -> string -> unit
+(** Set variable (just a wrapper around {!Whenfile.set_variable}). *)
+
+val set_variable_float : string -> float -> unit
+(** Set variable (just a wrapper around {!Whenfile.set_variable}). *)
index 6c0c6b0..d80c09f 100644 (file)
 EXTRA_DIST = test_run.sh $(TESTS) $(TESTS:.ml=.ml.expected)
 
 TESTS_ENVIRONMENT = ./test_run.sh
-TESTS = t100_counter.ml t101_updown.ml t102_manyjobs.ml
+TESTS = \
+       t100_counter.ml \
+       t101_updown.ml \
+       t102_manyjobs.ml \
+       t200_ocaml_jobnames.ml \
+       t201_ocaml_set_variable.ml
 
 OCAMLPACKAGES = -package unix,num,camlp4.lib,calendar,rpc -I ../../lib
 
diff --git a/tests/jobs/t200_ocaml_jobnames.ml b/tests/jobs/t200_ocaml_jobnames.ml
new file mode 100644 (file)
index 0000000..c003700
--- /dev/null
@@ -0,0 +1,35 @@
+(* whenjobs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* Test OCaml job names. *)
+
+let prefix = "prefix_"
+
+job (prefix ^ "job")
+every 2 seconds :
+<<
+  echo $JOBSERIAL $JOBNAME >\> $HOME/test_output
+  whenjobs --set counter 1
+>>
+
+job (prefix ^ "finished")
+when counter == 1 :
+<<
+  echo $JOBSERIAL $JOBNAME >\> $HOME/test_output
+  whenjobs --daemon-stop
+>>
diff --git a/tests/jobs/t200_ocaml_jobnames.ml.expected b/tests/jobs/t200_ocaml_jobnames.ml.expected
new file mode 100644 (file)
index 0000000..0463a73
--- /dev/null
@@ -0,0 +1,2 @@
+1 prefix_job
+2 prefix_finished
diff --git a/tests/jobs/t201_ocaml_set_variable.ml b/tests/jobs/t201_ocaml_set_variable.ml
new file mode 100644 (file)
index 0000000..50ee5ab
--- /dev/null
@@ -0,0 +1,34 @@
+(* whenjobs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* Test setting a variable. *)
+
+let () =
+  Whentools.set_variable_int "counter" 99
+
+every second :
+<<
+  echo $JOBSERIAL $JOBNAME $counter >\> $HOME/test_output
+  whenjobs --set counter $(($counter+1))
+>>
+
+when counter > 100 :
+<<
+  echo $JOBSERIAL $JOBNAME $counter >\> $HOME/test_output
+  whenjobs --daemon-stop
+>>
diff --git a/tests/jobs/t201_ocaml_set_variable.ml.expected b/tests/jobs/t201_ocaml_set_variable.ml.expected
new file mode 100644 (file)
index 0000000..1cad696
--- /dev/null
@@ -0,0 +1,3 @@
+1 job$1 99
+2 job$1 100
+3 job$2 101
index 9398eb4..5d4c47a 100644 (file)
@@ -18,6 +18,9 @@
 
 open Printf
 
+(* Ensures that Whentools module is linked to the program. *)
+let _ = Whentools.set_variable
+
 (* This program is passed a single argument, which is the .cmo file to
  * dynamically load.
  *)
index 3383c91..8472672 100644 (file)
@@ -20,6 +20,9 @@ open Big_int
 open Unix
 open Printf
 
+(* Ensures that Whentools module is linked to the whenjobs tool. *)
+let _ = Whentools.set_variable
+
 let libdir = ref Libdir.libdir
 
 let jobsdir =
index 43fe847..368f413 100644 (file)
@@ -396,14 +396,18 @@ ran, then this evaluates to true, else false.
 
 This is the same as writing C<prev variable E<gt> variable>.
 
-B<Note:> There is a subtle and difficult problem with using the
-I<decreases> operator: The first time the expression is evaluated, the
-job has (by definition) not yet run.  Therefore C<prev variable>
-evaluates to C<""> (see definition of I<prev> above).  Since
-C<"" E<lt> everything>, the I<decreases> operator evaluates to
-false, and since this usually means the job does not run, the
-operator always evaluates to false.  A future version of whenjobs
-will address this problem.
+B<Note:> There is a subtle gotcha with the I<decreases> operator: The
+first time the expression is evaluated, the job has (by definition)
+not yet run.  Therefore C<prev variable> evaluates to C<""> (see
+definition of I<prev> above).  Since it is always true that
+
+ "" < anything
+
+the I<decreases> operator evaluates to false, and since this usually
+means the job does not run, the operator always evaluates to false.
+
+To fix this, ensure that the variable is initialized (see
+L</SETTING THE INITIAL VALUE OF VARIABLES> below).
 
 =item B<reloaded ()>
 
@@ -411,9 +415,7 @@ This evaluates to true the first time the expression is evaluated
 after the jobs file has been reloaded or the daemon restarted.
 Thereafter it evaluates to false.
 
-You can use this to initialize variables, but note that this does not
-solve the I<decreases> operator problem described above, because
-variables are initialized too late to affect that.
+Don't use this to initialize variables: it won't do what you mean.
 
 =item B<false>
 
@@ -541,15 +543,53 @@ which creates two jobs called C<"daily_virus_scan"> and
 C<"daily_disk_check"> (C<^> is the OCaml string concatenation
 operator).
 
+OCaml expressions have access to a library of functions called
+B<Whentools> which is described below.  It lets you set variables,
+create jobs algorithmically, etc.
+
 The OCaml expressions run once, when the jobs file is being loaded or
 reloaded.
 
+=head3 SETTING THE INITIAL VALUE OF VARIABLES
+
+Variables are created when they are referenced, and until set they
+have the value empty string (just like the shell).  Across file
+reloads, the previous values of variables is preserved.
+
+To initialize a variable to a known value when the jobs file is
+loaded, call one of the C<Whentools.set_variable*> functions as in
+this example:
+
+ let () =
+   Whentools.set_variable "name" "Richard";
+   Whentools.set_variable_int "counter" 0
+
+=head3 WHENTOOLS LIBRARY
 
+=over 4
+
+=item B<Whentools.set_variable> I<name> I<string>
+
+Set variable I<name> to the string.
+
+=item B<Whentools.set_variable_bool> I<name> I<b>
 
+Set variable I<name> to the boolean value I<b>.
 
+=item B<Whentools.set_variable_int> I<name> I<i>
 
+Set variable I<name> to the integer value I<i>.
 
+=item B<Whentools.set_variable_string> I<name> I<s>
 
+Set variable I<name> to the string value <s>.  This is
+the same as I<Whentools.set_variable>.
+
+=item B<Whentools.set_variable_float> I<name> I<f>
+
+Set variable I<name> to the floating point value I<f>.
+
+=back
 
 =head1 FILES