blob: e9c034091cc802fafae11bf2937210d0b12ce419 [file] [log] [blame]
#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
'''
multidd - run multiple dd concurrently to determine disk throughput
Usage: multidd {-i infile} {-o outfile} [-B blocksz] [-S filesz]
-i infile where infile specifies the path of input file
-o outfile where outfile specifies the path of output file
-B blocksz where blocksz is the size of each I/O block
[default=8KB]
-S filesz where filesz is the size of the file to write
[default=2X system RAM]
Multiple -i and -o arguments may be specified but they must pair up.
e.g. multidd -i /dev/zero -o /dbfast1/ddtest -B 8kb -S 2gb
'''
import sys, os, getopt, math
################
def usage(exitarg):
print __doc__
sys.exit(exitarg)
################
def run(cmd):
f = None
ok = False
out = None
try:
f = os.popen(cmd)
out = f.read()
ok = not f.close()
except:
f.close()
ok = False
return (ok, out)
################
def getPlatform():
if sys.platform.find('linux') >= 0: return 'linux'
if sys.platform.find('darwin') >= 0: return 'darwin'
if sys.platform.find('sunos5') >= 0: return 'sunos5'
return '?'
################
def getMemory():
if getPlatform() == 'linux':
ok, out = run("sh -c 'cat /proc/meminfo | grep MemTotal'")
if not ok: return '?'
list = out.strip().split(' ')
val = int(list[len(list) - 2])
factor = list[len(list) - 1]
if factor == 'kB': return val * 1024
return '?'
if getPlatform() == 'darwin':
ok, out = run("sysctl hw.physmem")
if not ok: return '?'
list = out.strip().split(' ')
val = int(list[1])
return val
if getPlatform() == 'sunos5':
ok, out = run("sh -c \"/usr/sbin/prtconf | awk '/^Memory/{print}'\"")
if not ok: return '?'
list = out.strip().split(' ')
val = int(list[2])
factor = list[3]
if factor == 'Megabytes': return val * 1024 * 1024
return '?'
return '?'
################
def parseMemorySize(line):
factor = 1
try:
line = line.strip().upper()
if line.endswith('B'): line = line[:-1]
if line.endswith('G'): factor = 1024 * 1024 * 1024
elif line.endswith('M'): factor = 1024 * 1024
elif line.endswith('K'): factor = 1024
if factor > 1: line = line[:-1]
return int(line) * factor
except:
return 0
opt = {}
opt['-i'] = []
opt['-o'] = []
opt['-B'] = parseMemorySize('8KB')
opt['-S'] = 0
################
def parseCommandLine():
global opt
try:
(options, args) = getopt.getopt(sys.argv[1:], '?i:o:B:S:')
except:
e = sys.exc_info()
usage('Error: %s %s' % (e[0], e[1]))
for (switch, val) in options:
if (switch == '-?'):
usage(0)
elif (switch[1] in 'io'):
opt[switch].append(val)
elif (switch[1] in 'BS'):
opt[switch] = parseMemorySize(val)
if opt['-S'] == '?': sys.exit('Error: unable to obtain system RAM size')
if opt['-S'] < 0: usage('Error: invalid -S filesz parameter')
if opt['-B'] <= 0: usage('Error: invalid -B blocksz parameter')
if opt['-B'] > 1024*1024: usage('Error: maximum 1MB for -B parameter')
if len(opt['-i']) != len(opt['-o']): usage('Error: -i and -o parameters must pair up')
if len(opt['-i']) == 0: usage('Error: missing -i and -o parameters')
################
parseCommandLine()
if opt['-S'] == 0: opt['-S'] = getMemory() * 2
if opt['-S'] < opt['-B']: opt['-S'] = opt['-B']
cmd = []
pfile = []
blocksz = opt['-B']
cnt = int(math.ceil(opt['-S'] / blocksz))
totalBytes = 0
for i in xrange(len(opt['-i'])):
ifile = opt['-i'][i]
ofile = opt['-o'][i]
cmd.append('dd if=%s of=%s count=%d bs=%d' % (ifile, ofile, cnt, blocksz))
totalBytes += cnt * blocksz
for c in cmd:
print c
pfile.append(os.popen(c))
for f in pfile:
ok = False
try:
print f.read()
ok = not f.close()
f = None
except:
if f: f.close()
ok = False
if not ok: sys.exit(1)
os.system('sync')
print 'multidd total bytes ', totalBytes