forked from parallel-fs-utils/fs-drift
/
invoke_process.py
145 lines (129 loc) · 5.44 KB
/
invoke_process.py
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
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
invoke_process.py
launch multiple subprocesses running FsDriftThread instance
Licensed under the Apache License at http://www.apache.org/licenses/LICENSE-2.0
See Appendix on this page for instructions pertaining to license.
'''
import os
import time
import multiprocessing
import pickle
import opts
import worker_thread
import fsd_log
import common
from common import FsDriftException, OK, NOTOK, deltree
from sync_files import write_pickle
# this class launches multiple threads with FsDriftWorkload instances
# we do this because we can use > 1 core this way, with python threading,
# a python process doesn't really use > 1 core because of the GIL (global lock)
# occasional status reports could be sent back using pipe as well
class subprocess(multiprocessing.Process):
def __init__(self, invocation):
multiprocessing.Process.__init__(self)
(conn1, conn2) = multiprocessing.Pipe(False)
self.receiver = conn1 # master process receives test result data here
self.sender = conn2 # slave process sends test result data here
self.invoke = invocation # all workload generated by this object
# the following fields are filled in by the retrieve() method
def run(self):
wkr = self.invoke
try:
wkr.do_workload()
wkr.log.debug('exiting subprocess and returning invoke for ' + wkr.tid)
except Exception as e:
print('Exception seen in thread %s host %s (tail %s) ' %
(wkr.tid, wkr.onhost, wkr.log_fn()))
wkr.log.error(str(e))
finally:
wkr.rsptimes = None # response time array already saved to file
wkr.params = None
wkr.log = None # log objects cannot be serialized
wkr.buf = None
wkr.biggest_buf = None
ctrs = wkr.ctrs
self.sender.send(wkr.status)
self.sender.send(wkr.elapsed_time)
self.sender.send(ctrs)
# parent that launched the subprocess retrieves results here
def retrieve(self):
self.invoke.status = self.receiver.recv()
self.invoke.elapsed_time = self.receiver.recv()
self.invoke.ctrs = self.receiver.recv()
# null out sub-objects so that pickling doesn't fail
self.receiver = None
self.sender = None
# so you can just do "python invoke_process.py" to test it
if __name__ == '__main__':
import unittest2
class Test(unittest2.TestCase):
workload_table = [
'read, 2',
'random_read, 1',
'random_write, 1',
'append, 4',
'delete, 0.1',
'hardlink, 0.01',
'softlink, 0.02',
'truncate, 0.05',
'rename, 1',
'create, 4']
def setUp(self):
self.params = opts.parseopts()
self.params.duration = 2
self.params.workload_table_csv_path = '/tmp/weights.csv'
self.log = fsd_log.start_log('invoke_process')
def resetDir(self):
deltree(self.params.top_directory)
os.mkdir(self.params.top_directory)
os.mkdir(self.params.network_shared_path)
write_pickle(self.params.param_pickle_path, self.params)
def test_multiproc(self):
self.log.info('starting test')
self.resetDir()
with open('/tmp/weights.csv', 'w') as w_f:
w_f.write( '\n'.join(Test.workload_table))
thread_ready_timeout = 4
thread_count = 4
invokeList = []
for j in range(0, thread_count):
s = worker_thread.FsDriftWorkload(self.params)
s.tid = str(j)
invokeList.append(s)
threadList = []
for s in invokeList:
threadList.append(subprocess(s))
for t in threadList:
t.start()
threads_ready = True
self.log.info('threads started')
for i in range(0, thread_ready_timeout):
threads_ready = True
for s in invokeList:
thread_ready_file = s.gen_thread_ready_fname(s.tid)
if not os.path.exists(thread_ready_file):
threads_ready = False
if threads_ready:
break
time.sleep(1)
if not threads_ready:
raise FsDriftException('threads did not show up within %d seconds'
% thread_ready_timeout)
time.sleep(1)
self.log.info('threads awaiting starting gun')
common.touch(self.params.starting_gun_path)
for t in threadList:
t.retrieve()
t.join()
self.log.info('thread ' + t.invoke.tid + ' finished')
for t in threadList:
if t.invoke.elapsed_time == -1.0:
raise FsDriftException('subprocess never got elapsed time')
if t.invoke.status != OK:
raise FsDriftException('subprocess status %d for thread %s' % (t.invoke.status, t.invoke.tid))
print('thread %s counters:\n%s' % (t.invoke.tid, str(t.invoke.ctrs)))
if t.invoke.ctrs.read_bytes == 0:
raise FsDriftException('subprocess never read any data')
unittest2.main()