Re: [CFT] multiple instance support in rc.d script

2014-10-22 Thread Chad J. Milios
On 10/22/14 17:02, Jim Riggs wrote:
> On 16 Oct 2014, at 20:22, Hiroki Sato  wrote:
> 
>> I would like your feedback and testers of the attached patch.  This
>> implements multiple instance support in rc.d scripts.  You can try it
>> by replacing /etc/rc.subr with the attached one.
> 
> 
> I really like the idea, as I have written at least 2 or 3 ports in which I 
> have needed support for multiple "profiles" (as I have seen them called in 
> several ports). So, I had to duplicate the multiple-instance logic in the rc 
> script for each. This would save all of that aggravation.
> 
> The only concern I have with generalizing the approach in rc.subr, though, is 
> that not every app/daemon/script can or should support it. I worry that some 
> things if run multiple times may stomp on each other or corrupt data or break 
> something. It seems that there should be a way for each rc script to either 
> opt in or opt out of multiple instance support. I don't know which is better. 
> Opt-in is probably safer, but then core devs and port maintainers have to 
> make specific changes to support it. :-\
> 
> Thoughts?

Opt-in please
___
freebsd-ports@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ports
To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"


[CFT] multiple instance support in rc.d script

2014-10-16 Thread Hiroki Sato
[Please reply to freebsd-rc@]

Hi,

 I would like your feedback and testers of the attached patch.  This
 implements multiple instance support in rc.d scripts.  You can try it
 by replacing /etc/rc.subr with the attached one.

 More details are as follow.  Typically, an rc.d/foo script has the
 following structure and rc.conf variables:

   /etc/rc.d/foo:
   
   name=foo
   rcvar=foo_enable
   ...
   load_rc_command $name
   run_rc_command $*
   

   /etc/rc.conf:
   
   foo_enable="YES"
   foo_flags="-f -l -a -g"
   

 The above supports one instance for one script.  After replacing
 rc.subr, you can specify additional instances in rc.conf:

   /etc/rc.conf:
   
   foo_instances="one two"

   foo_one_enable="YES"
   foo_one_flags="-f -l -a -g"

   foo_two_enable="YES"
   foo_two_flags="-F -L -A -G"
   

 $foo_instances defines instances by space-separated list of instance
 names, and rc.conf variables for them are something like
 ${name}_${instname}_enable.  The following command

  # service foo start

 starts foo_one and foo_two with the specified flags.  Instances can
 be specified in the following form:

  # service foo start:one

 or multiple instances in a particular order:

  # service foo start:two,one

 Basically, no change is required for the rc.d/foo script itself.
 However, there is a problem that default values of the instantiated
 variables are not defined.

 For example, if an rc.d/script uses $foo_mode, you need to define
 $foo_one_mode.  The default value of $foo_mode is usually defined in
 etc/defaults/rc.conf for rc.d scripts in the base system and ":
 ${foo_mode:=value}" idiom in scripts from Ports Collection.  So all
 of the variables should be defined for each instance, too.  As you
 noticed, this is not easy without editing the script itself.

 To alleviate this, set_rcvar() can be used:

   /etc/rc.d/foo:
   
   name=foo
   rcvar=foo_enable

   set_rcvar foo_enable YES "Enable $name"
   set_rcvar foo_program"/tmp/test" "Command for $name"
   ...
   load_rc_command $name
   run_rc_command $*
   

 The three arguments are varname, default value, and description.  If
 a variable is defined by set_rcvar(), default values instantiated
 variables will be set automatically---foo_one_program is set by
 foo_program if it is not defined.

 This approach still has another problem.  set_rcvar() is not
 supported in all branches, so a script using it does not work in old
 supported branches.  One solution which can be used for scripts in
 Ports Collection is adding both definitions before and after
 load_rc_command() until EoL of old branches like this:

   /etc/rc.d/foo:
   
   name=foo
   rcvar=foo_enable

   if type set_rcvar >/dev/null 2>&1; then
set_rcvar foo_enableYES "Enable $name"
set_rcvar foo_program   "/tmp/test" "Command for $name"
   fi
   ...
   load_rc_command $name

   # will be removed after all supported branches have set_rcvar().
   if ! type set_rcvar >/dev/null 2>&1; then
: ${foo_enable:="YES"}
: ${foo_program:="/tmp/test"}
for _i in $foo_instances; do
for _j in enable program; do
eval : \${foo_${_i}_enable:=\$foo_$_j}
done
done
   fi

   run_rc_command $*
   

 This is a bit ugly but should work fine.

 I am using this patch to invoke multiple named (caching
 server/contents server) and syslogd (local only/listens INET/INET6
 socket only) daemons.  While $foo_instances is designed as a
 user-defined knob, this can be applied to software which need to
 invoke multiple/different daemons which depend on each other in a
 script, too.

 I am feeling this patch still needs more careful review from others.
 Any comments are welcome.  Thank you.

-- Hiroki
Index: etc/rc.subr
===
--- etc/rc.subr	(revision 272976)
+++ etc/rc.subr	(working copy)
@@ -698,7 +698,10 @@
 #		"start stop restart rcvar status poll ${extra_commands}"
 #	If there's a match, run ${argument}_cmd or the default method
 #	(see below).
+#	_run_rc_command0() is the main routine and run_rc_command() is
+#	a wrapper to handle multiple instances.
 #
+#
 #	If argument has a given prefix, then change the operation as follows:
 #		Prefix	Operation
 #		--	-
@@ -755,6 +758,9 @@
 #
 #	${name}_nice	n	Nice level to run ${command} at.
 #
+#	${name}_pidfile	n	This to be used in /etc/rc.conf to override
+#${pidfile}.
+#
 #	${name}_user	n	User to run ${command} as, using su(1) if not
 #using ${name}_chroot.
 #Requires /usr to be mounted.
@@ -863,6 +869,57 @@
 #
 run_rc_command()
 {
+	local _act _instances _name _desc _rcvar
+
+	_act=$1
+	shift
+	eval _instances=\$${name}_instances
+
+	# Check if instance is specified, e.g. "start:instance,...".
+	case ${_act%:*} in
+	$_act)	;;			# no instance specified
+	*)
+		_instances=$(echo ${_act#*:} | tr "," " "