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");
}
|