Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite20ed5e

Browse files
committed
Add functions that return PIDs of various processes
1 parent5bc608e commite20ed5e

File tree

3 files changed

+140
-9
lines changed

3 files changed

+140
-9
lines changed

‎testgres/connection.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(self, node, dbname=None, username=None, password=None):
3434
username=usernameordefault_username()
3535

3636
self._node=node
37+
self._backend_pid=None
3738

3839
self._connection=pglib.connect(
3940
database=dbname,
@@ -52,6 +53,12 @@ def node(self):
5253
defconnection(self):
5354
returnself._connection
5455

56+
@property
57+
defbackend_pid(self):
58+
ifself._backend_pidisNone:
59+
self._backend_pid=self.execute("select pg_backend_pid();")[0][0]
60+
returnself._backend_pid
61+
5562
@property
5663
defcursor(self):
5764
returnself._cursor

‎testgres/node.py

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
importsix
66
importsubprocess
77
importtime
8+
importwarnings
9+
10+
try:
11+
importpsutil
12+
exceptImportError:
13+
psutil=None
814

915
fromshutilimportrmtree
1016
fromsiximportraise_from
@@ -48,7 +54,8 @@
4854
ExecUtilException, \
4955
QueryException, \
5056
StartNodeException, \
51-
TimeoutException
57+
TimeoutException, \
58+
TestgresException
5259

5360
from .loggerimportTestgresLogger
5461

@@ -116,7 +123,11 @@ def __exit__(self, type, value, traceback):
116123

117124
@property
118125
defpid(self):
119-
returnself.get_pid()
126+
returnself.get_main_pid()
127+
128+
@property
129+
defauxiliary_pids(self):
130+
returnself.get_auxiliary_pids()
120131

121132
@property
122133
defmaster(self):
@@ -417,7 +428,7 @@ def status(self):
417428
elife.exit_code==4:
418429
returnNodeStatus.Uninitialized
419430

420-
defget_pid(self):
431+
defget_main_pid(self):
421432
"""
422433
Return postmaster's PID if node is running, else 0.
423434
"""
@@ -428,7 +439,73 @@ def get_pid(self):
428439
returnint(f.readline())
429440

430441
# for clarity
431-
return0
442+
returnNone
443+
444+
defget_child_processes(self):
445+
''' Returns child processes for this node '''
446+
447+
ifpsutilisNone:
448+
warnings.warn("psutil module is not installed")
449+
returnNone
450+
451+
try:
452+
postmaster=psutil.Process(self.pid)
453+
exceptpsutil.NoSuchProcess:
454+
returnNone
455+
456+
returnpostmaster.children(recursive=True)
457+
458+
defget_auxiliary_pids(self):
459+
''' Returns dict with pids of auxiliary processes '''
460+
461+
children=self.get_child_processes()
462+
ifchildrenisNone:
463+
returnNone
464+
465+
result= {}
466+
forchildinchildren:
467+
line=child.cmdline()[0]
468+
ifline.startswith('postgres: checkpointer'):
469+
result['checkpointer']=child.pid
470+
elifline.startswith('postgres: background writer'):
471+
result['bgwriter']=child.pid
472+
elifline.startswith('postgres: walwriter'):
473+
result['walwriter']=child.pid
474+
elifline.startswith('postgres: autovacuum launcher'):
475+
result['autovacuum_launcher']=child.pid
476+
elifline.startswith('postgres: stats collector'):
477+
result['stats']=child.pid
478+
elifline.startswith('postgres: logical replication launcher'):
479+
result['logical_replication_launcher']=child.pid
480+
elifline.startswith('postgres: walreceiver'):
481+
result['walreceiver']=child.pid
482+
elifline.startswith('postgres: walsender'):
483+
result.setdefault('walsenders', [])
484+
result['walsenders'].append(child.pid)
485+
elifline.startswith('postgres: startup'):
486+
result['startup']=child.pid
487+
488+
returnresult
489+
490+
defget_walsender_pid(self):
491+
''' Returns pid of according walsender for replica '''
492+
493+
ifnotself._master:
494+
raiseTestgresException("This node is not a replica")
495+
496+
children=self._master.get_child_processes()
497+
ifchildrenisNone:
498+
returnNone
499+
500+
sql='select application_name, client_port from pg_stat_replication'
501+
forname,client_portinself._master.execute(sql):
502+
ifname==self.name:
503+
forchildinchildren:
504+
line=child.cmdline()[0]
505+
ifline.startswith('postgres: walsender')andstr(client_port)inline:
506+
returnchild.pid
507+
508+
returnNone
432509

433510
defget_control_data(self):
434511
"""

‎tests/test_simple.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,27 +205,27 @@ def test_status(self):
205205

206206
# check statuses after each operation
207207
withget_new_node()asnode:
208-
self.assertEqual(node.pid,0)
208+
self.assertIsNone(node.pid)
209209
self.assertEqual(node.status(),NodeStatus.Uninitialized)
210210

211211
node.init()
212212

213-
self.assertEqual(node.pid,0)
213+
self.assertIsNone(node.pid)
214214
self.assertEqual(node.status(),NodeStatus.Stopped)
215215

216216
node.start()
217217

218-
self.assertNotEqual(node.pid,0)
218+
self.assertIsNotNone(node.pid)
219219
self.assertEqual(node.status(),NodeStatus.Running)
220220

221221
node.stop()
222222

223-
self.assertEqual(node.pid,0)
223+
self.assertIsNone(node.pid)
224224
self.assertEqual(node.status(),NodeStatus.Stopped)
225225

226226
node.cleanup()
227227

228-
self.assertEqual(node.pid,0)
228+
self.assertIsNone(node.pid)
229229
self.assertEqual(node.status(),NodeStatus.Uninitialized)
230230

231231
deftest_psql(self):
@@ -702,6 +702,53 @@ def test_version_management(self):
702702
self.assertTrue(b>c)
703703
self.assertTrue(a>c)
704704

705+
deftest_pids(self):
706+
try:
707+
importpsutil
708+
exceptImportError:
709+
psutil=None
710+
711+
master_processes= (
712+
'checkpointer',
713+
'bgwriter',
714+
'walwriter',
715+
'autovacuum_launcher',
716+
'stats',
717+
'logical_replication_launcher',
718+
'walsenders',
719+
)
720+
repl_processes= (
721+
'startup',
722+
'checkpointer',
723+
'bgwriter',
724+
'stats',
725+
'walreceiver',
726+
)
727+
728+
withget_new_node('master')asmaster:
729+
master.init().start()
730+
731+
self.assertIsNotNone(master.pid)
732+
withmaster.connect()ascon:
733+
self.assertTrue(con.backend_pid>0)
734+
735+
withmaster.backup()asbackup:
736+
withbackup.spawn_replica('repl',True)asrepl:
737+
repl.start()
738+
ifpsutilisNone:
739+
self.assertIsNone(master.auxiliary_pids)
740+
self.assertIsNone(repl.auxiliary_pids)
741+
else:
742+
master_pids=master.auxiliary_pids
743+
fornameinmaster_processes:
744+
self.assertTrue(nameinmaster_pids)
745+
self.assertTrue(len(master_pids['walsenders'])==1)
746+
747+
repl_pids=repl.auxiliary_pids
748+
fornameinrepl_processes:
749+
self.assertTrue(nameinrepl_pids)
750+
self.assertTrue(repl.get_walsender_pid()==master_pids['walsenders'][0])
751+
705752

706753
if__name__=='__main__':
707754
unittest.main()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp