aboutsummaryrefslogtreecommitdiff
path: root/src/test/modules/test_aio/t/002_io_workers.pl
blob: af5fae15ea78ed9c2fab0f89cd22a18f9569751d (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
# Copyright (c) 2025, PostgreSQL Global Development Group

use strict;
use warnings FATAL => 'all';

use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
use List::Util qw(shuffle);


my $node = PostgreSQL::Test::Cluster->new('worker');
$node->init();
$node->append_conf(
	'postgresql.conf', qq(
io_method=worker
));

$node->start();

# Test changing the number of I/O worker processes while also evaluating the
# handling of their termination.
test_number_of_io_workers_dynamic($node);

$node->stop();

done_testing();


sub test_number_of_io_workers_dynamic
{
	my $node = shift;

	my $prev_worker_count = $node->safe_psql('postgres', 'SHOW io_workers');

	# Verify that worker count can't be set to 0
	change_number_of_io_workers($node, 0, $prev_worker_count, 1);

	# Verify that worker count can't be set to 33 (above the max)
	change_number_of_io_workers($node, 33, $prev_worker_count, 1);

	# Try changing IO workers to a random value and verify that the worker
	# count ends up as expected. Always test the min/max of workers.
	#
	# Valid range for io_workers is [1, 32]. 8 tests in total seems
	# reasonable.
	my @io_workers_range = shuffle(1 ... 32);
	foreach my $worker_count (1, 32, @io_workers_range[ 0, 6 ])
	{
		$prev_worker_count =
		  change_number_of_io_workers($node, $worker_count,
			$prev_worker_count, 0);
	}
}

sub change_number_of_io_workers
{
	my $node = shift;
	my $worker_count = shift;
	my $prev_worker_count = shift;
	my $expect_failure = shift;
	my ($result, $stdout, $stderr);

	($result, $stdout, $stderr) =
	  $node->psql('postgres', "ALTER SYSTEM SET io_workers = $worker_count");
	$node->safe_psql('postgres', 'SELECT pg_reload_conf()');

	if ($expect_failure)
	{
		ok( $stderr =~
			  /$worker_count is outside the valid range for parameter "io_workers"/,
			"updating number of io_workers to $worker_count failed, as expected"
		);

		return $prev_worker_count;
	}
	else
	{
		is( $node->safe_psql('postgres', 'SHOW io_workers'),
			$worker_count,
			"updating number of io_workers from $prev_worker_count to $worker_count"
		);

		check_io_worker_count($node, $worker_count);
		terminate_io_worker($node, $worker_count);
		check_io_worker_count($node, $worker_count);

		return $worker_count;
	}
}

sub terminate_io_worker
{
	my $node = shift;
	my $worker_count = shift;
	my ($pid, $ret);

	# Select a random io worker
	$pid = $node->safe_psql(
		'postgres',
		qq(SELECT pid FROM pg_stat_activity WHERE
			backend_type = 'io worker' ORDER BY RANDOM() LIMIT 1));

	# terminate IO worker with SIGINT
	is(PostgreSQL::Test::Utils::system_log('pg_ctl', 'kill', 'INT', $pid),
		0, "random io worker process signalled with INT");

	# Check that worker exits
	ok( $node->poll_query_until(
			'postgres',
			qq(SELECT COUNT(*) FROM pg_stat_activity WHERE pid = $pid), '0'),
		"random io worker process exited after signal");
}

sub check_io_worker_count
{
	my $node = shift;
	my $worker_count = shift;

	ok( $node->poll_query_until(
			'postgres',
			qq(SELECT COUNT(*) FROM pg_stat_activity WHERE backend_type = 'io worker'),
			$worker_count),
		"io worker count is $worker_count");
}