summaryrefslogtreecommitdiffhomepage
path: root/subr/ex_pkg_dispatch.subr
blob: a01315601525885398d1e249f734e196d7a5a539 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#
# set -o noglob is assumed.
# WARNING: ex_pkg_dispatch(), its caller, and its callers must _NOT_ be executed
# as part of conditional evaluation, e.g. if, until, while, !, or && and ||, as
# doing so would inhibit set -o errexit during execution of this function and its
# subshell(!).  Instead, call ex_pkg_dispatch() and subsequently evaluate ${?}.
#

exp_pkg_check_depends() {
	local _group_name="${1}" _pkg_depends="${2}" _pkg_name="${3}" _dependfl=0;
	if ! [ -n "${_restart}" ]\
	|| [ "${ARG_RESTART_RECURSIVE:-0}" -ge 1 ]; then
		for _pkg_name_depend in ${_pkg_depends}; do
			if [ -n "$(ex_rtl_lsearch "${_pkgs_wait}" "${_pkg_name_depend}")" ]\
			|| [ -z "$(ex_rtl_lsearch "${_pkgs_complete}" "${_pkg_name_depend}")" ]; then
				_dependfl=1; break;
			fi;
		done;
	fi;
	return "${_dependfl}";
};

exp_pkg_dispatch_group() {
	local _njob=0 _pkg_depends="" _pkg_name="" _pkg_skipfl=0;
	for _njob in $(seq 1 $((${_njobs_max}-${_njobs}))); do
		for _pkg_name in ${_pkg_names}; do
			_pkg_skipfl=0;
			if [ -z "$(ex_rtl_lsearch "${_pkgs_complete}" "${_pkg_name}")" ]\
			&& [ -z "$(ex_rtl_lsearch "${_pkgs_wait}" "${_pkg_name}")" ]\
			&& _pkg_depends="$(exp_pkg_expand_packages $(ex_rtl_get_var_unsafe "PKG_$(ex_rtl_toupper "${_pkg_name}")_DEPENDS"))"\
			&& exp_pkg_check_depends "${_group_name}" "${_pkg_depends}" "${_pkg_name}"	\
			&& exp_pkg_dispatch_package "${_dispatch_fn}" "${_group_name}"			\
					"${_pkg_name}" "${_restart}" "${_restart_at}"			\
					"${_stderrout_path}" "${_pipe_path}"; then
				_pkgs_found_new="${_pkgs_found_new:+${_pkgs_found_new} }${_pkg_name}";
				break;
			elif [ "${_pkg_skipfl:-0}" -eq 1 ]; then
				_pkgs_found_new="${_pkgs_found_new:+${_pkgs_found_new} }${_pkg_name}";
				continue;
			fi;
		done;
	done;
};

exp_pkg_dispatch_package() {
	local _dispatch_fn="${1}" _group_name="${2}" _pkg_name="${3}" _restart="${4}" _restart_at="${5}"	\
		_stderrout_path="${6}" _pipe_path="${7}" _pkg_name_uc="" _rc=0;
	_pkg_name_uc="$(ex_rtl_toupper "${_pkg_name}")";
	if [ -n "$(ex_rtl_get_var_unsafe PKG_${_pkg_name_uc}_DISABLED)" ]; then
		_pkgs_complete="${_pkgs_complete:+${_pkgs_complete} }${_pkg_name}";
		_pkg_names="$(ex_rtl_lfilter "${_pkg_names}" "${_pkg_name}")";
		: $((_pkgs_count+=1)); _pkg_skipfl=1; _rc=1;
		"${_dispatch_fn}" disabled_pkg "${_group_name}" "${_pkg_name}" "${_pkgs_count}" "${_pkgs_count_max}";
	elif ex_pkg_state_test "${_pkg_name}" finish\
	&& [ -z "$(ex_rtl_lsearch "${_restart}" "${_pkg_name}")" ]\
	&& [ "${ARG_RESTART_RECURSIVE:-0}" -ne 2 ]; then
		_pkgs_complete="${_pkgs_complete:+${_pkgs_complete} }${_pkg_name}";
		_pkg_names="$(ex_rtl_lfilter "${_pkg_names}" "${_pkg_name}")";
		: $((_pkgs_count+=1)); _pkg_skipfl=1; _rc=1;
		"${_dispatch_fn}" skipped_pkg "${_group_name}" "${_pkg_name}" "${_pkgs_count}" "${_pkgs_count_max}";
	else
		: $((_pkgs_count+=1)); _pkgs_wait="${_pkgs_wait:+${_pkgs_wait} }${_pkg_name}";
		_stderrout_path="${BUILD_WORKDIR}/${_pkg_name}_stderrout.log";
		"${_dispatch_fn}" start_pkg "${_group_name}" "${_pkg_name}" "${_pkgs_count}" "${_pkgs_count_max}";
		(set -o errexit -o noglob; BUILD_IS_PARENT=0;
		ex_pkg_env "${_group_name}" "${_pkg_name}" "${_restart_at}";
		ex_pkg_exec "${_group_name}" "${_pkg_name}" "${_restart_at}"					\
			"${_dispatch_fn}";) 1>"${_stderrout_path}" 2>&1 3>"${_pipe_path}" &
		: $((_njobs+=1));
	fi;
	return "${_rc}";
};

exp_pkg_expand_packages() {
	local _pkg_depends="" _pkg_name="" _pkg_names="";
	for _pkg_name in "${@}"; do
		_pkg_depends="$(ex_rtl_get_var_unsafe "PKG_$(ex_rtl_toupper "${_pkg_name}")_DEPENDS")";
		if [ -n "${_pkg_depends}" ]; then
			_pkg_depends="$(exp_pkg_expand_packages ${_pkg_depends})";
			_pkg_names="${_pkg_names:+${_pkg_names} }${_pkg_depends} ${_pkg_name}";
		else
			_pkg_names="${_pkg_names:+${_pkg_names} }${_pkg_name}";
		fi;
	done;
	echo "${_pkg_names}";
};

exp_pkg_get_packages() {
	local _dispatch_fn="${1}" _group_name="${2}" _restart="${3}" _group_name_uc="";
	_group_name_uc="$(ex_rtl_toupper "${_group_name}")";
	_pkg_names="$(ex_rtl_get_var_unsafe ${_group_name_uc}_PACKAGES)";
	if [ -n "${_restart}" ]\
	&& ! ex_rtl_lmatch "ALL LAST" " " "${_restart}"; then
		_pkg_names="$(ex_rtl_lsearch "${_pkg_names}" "${_restart}")";
	fi;
	if ! [ -n "${_restart}" ]\
	|| [ "${ARG_RESTART_RECURSIVE:-0}" -ge 1 ]; then
		ex_rtl_log_msg vnfo "Resolving \`${_group_name}' dependencies...";
		_pkg_names="$(ex_rtl_uniq $(exp_pkg_expand_packages ${_pkg_names}))";
		ex_rtl_log_msg vnfo "Resolved \`${_group_name}' dependencies.";
	fi;
};

ex_pkg_dispatch() {
	local _group_name="${1}" _restart="${2}" _restart_at="${3}" _dispatch_fn="${4}" _pkgs_found_vname="${5}"	\
		_njob="" _njobs=0 _njobs_max=1 _pipe_msg="" _pipe_path="${BUILD_WORKDIR}/build.fifo"			\
		_pkg_name="" _pkg_names="" _pkgs_complete="" _pkgs_count=0 _pkgs_count_max=0 _pkgs_found=""		\
		_pkgs_found_new="" _pkgs_wait="" _script_rc=0 _stderrout_path="";
	"${_dispatch_fn}" start_group "${_group_name}" ""; ex_rtl_fileop mkdir "${BUILD_WORKDIR}";
	if exp_pkg_get_packages "${_dispatch_fn}" "${_group_name}" "${_restart}"\
	&& [ -n "${_pkg_names}" ]; then
		for _pkg_name in ${_pkg_names}; do
			: $((_pkgs_count_max+=1));
		done;
		if [ "${ARG_PARALLEL:-0}" -gt 1 ]; then
			_njobs_max="${DEFAULT_BUILD_CPUS}";
		fi;
		ex_rtl_fileop mkfifo "${_pipe_path}"; exp_pkg_dispatch_group;
		while [ "${_njobs:-0}" -gt 0 ]; do
			while read _pipe_msg; do
			case "${_pipe_msg%% *}" in
			done)	"${_dispatch_fn}" finish_pkg ${_pipe_msg#done };
				: $((_njobs-=1)); _pkg_name="${_pipe_msg#done * }";
				_pkgs_complete="${_pkgs_complete:+${_pkgs_complete} }${_pkg_name}";
				_pkg_names="$(ex_rtl_lfilter "${_pkg_names}" "${_pkg_name}")";
				_pkgs_wait="$(ex_rtl_lfilter "${_pkgs_wait}" "${_pkg_name}")";
				if [ "${_script_rc:-0}" -eq 0 ]; then
					exp_pkg_dispatch_group;
				fi;
				if [ "${_njobs}" -eq 0 ]\
				&& [ -z "${_pkg_names}" ]; then
					break;
				fi; ;;
			fail)	_script_rc=1; "${_dispatch_fn}" fail_pkg ${_pipe_msg#fail };
				[ $((_njobs-=1)) -eq 0 ] && break; ;;
			step)	"${_dispatch_fn}" step_pkg ${_pipe_msg#step }; ;;
			esac; done <>"${_pipe_path}";
		done;
		ex_rtl_fileop rm "${_pipe_path}";
	fi;
	"${_dispatch_fn}" finish_group "${_group_name}" "";
	if [ -n "${_pkgs_found_vname}" ]; then
		_pkgs_found="$(ex_rtl_get_var_unsafe "${_pkgs_found_vname}")";
		ex_rtl_set_var_unsafe "${_pkgs_found_vname}" "${_pkgs_found:+${_pkgs_found} }${_pkgs_found_new}";
	fi;
	return "${_script_rc}";
};

# vim:filetype=sh