sub code_loop_timeout()

in managementnode/lib/VCL/Module.pm [1500:1602]


sub code_loop_timeout {
	my $self = shift;
	unless (ref($self) && $self->isa('VCL::Module')) {
		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
		return;
	}
	
	my ($code_ref, $args_array_ref, $message, $total_wait_seconds, $attempt_delay_seconds, $message_interval_seconds) = @_;
	
	# Make sure the code reference argument was passed correctly
	if (!defined($code_ref)) {
		notify($ERRORS{'WARNING'}, 0, "code reference argument is undefined");
		return;
	}
	elsif (ref($code_ref) ne 'CODE') {
		notify($ERRORS{'WARNING'}, 0, "1st argument must be a code reference, not " . format_data($code_ref));
		return;
	}
	
	if (!defined($args_array_ref)) {
		notify($ERRORS{'WARNING'}, 0, "2nd argument (arguments to pass to code reference) is undefined");
		return;
	}
	elsif (!ref($args_array_ref) || ref($args_array_ref) ne 'ARRAY') {
		notify($ERRORS{'WARNING'}, 0, "2nd argument (arguments to pass to code reference) is not an array reference");
		return;
	}
	
	if (!defined($message)) {
		notify($ERRORS{'WARNING'}, 0, "3nd argument (message to display) is undefined");
		return;
	}
	elsif (!$message) {
		$message = 'executing code reference';
	}
	
	if (!defined($total_wait_seconds) || $total_wait_seconds !~ /^\d+$/) {
		notify($ERRORS{'WARNING'}, 0, "4th argument (total wait seconds) was not passed correctly");
		return;
	}
	
	if (!$attempt_delay_seconds) {
		$attempt_delay_seconds = 15;
	}
	elsif (defined($attempt_delay_seconds) && $attempt_delay_seconds !~ /^\d+$/) {
		notify($ERRORS{'WARNING'}, 0, "5th argument (attempt delay) was not passed correctly: $attempt_delay_seconds");
		return;
	}
	
	if ($message_interval_seconds) {
		if ($message_interval_seconds !~ /^\d+$/) {
			notify($ERRORS{'WARNING'}, 0, "6th argument (message interval) was not passed correctly");
			return;
		}
		
		# Message interval is pointless if it's set to a value less than $attempt_delay_seconds
		if ($message_interval_seconds < $attempt_delay_seconds) {
			$message_interval_seconds = 0;
		}
	}
	else {
		$message_interval_seconds = 0;
	}
	
	notify($ERRORS{'DEBUG'}, 0, "$message, maximum of $total_wait_seconds seconds");
	
	my $start_time = time();
	my $current_time = $start_time;
	my $end_time = ($start_time + $total_wait_seconds);
	
	# Loop until code returns true
	my $attempt = 0;
	while (($current_time = time) <= $end_time) {
		$attempt++;
		
		# Execute the code reference
		if (my $result = &$code_ref(@{$args_array_ref})) {
			notify($ERRORS{'OK'}, 0, "$message, code returned true");
			return $result;
		}
		
		$current_time = time;
		my $seconds_elapsed = ($current_time - $start_time);
		my $seconds_remaining = ($end_time > $current_time) ? ($end_time - $current_time) : 0;
		my $sleep_seconds = ($seconds_remaining < $attempt_delay_seconds) ? $seconds_remaining : $attempt_delay_seconds;
		
		if (!$message_interval_seconds) {
			notify($ERRORS{'OK'}, 0, "attempt $attempt: $message ($seconds_elapsed/$seconds_remaining elapsed/remaining seconds), sleeping for $sleep_seconds seconds");
		}
		elsif ($attempt == 1 || ($seconds_remaining <= $attempt_delay_seconds) || ($seconds_elapsed % $message_interval_seconds) < $attempt_delay_seconds) {
			notify($ERRORS{'OK'}, 0, "attempt $attempt: $message ($seconds_elapsed/$seconds_remaining elapsed/remaining seconds)");
		}
		
		if (!$sleep_seconds) {
			last;
		}
		
		sleep $sleep_seconds;
	}

	notify($ERRORS{'OK'}, 0, "$message, code did not return true after waiting $total_wait_seconds seconds");
	return 0;
} ## end sub code_loop_timeout