Alien-Libjio

 view release on metacpan or  search on metacpan

dist.ini  view on Meta::CPAN

; generate expected files automagically
[License]               ; based on the `license'
[Readme]                ; a small boilerplate blurb
[MetaYAML]              ; generate a META.yml
[ExecDir]               ; include `bin/' as executables
[ShareDir]              ; include `share/' for File::ShareDir
[ModuleBuild::Custom]   ; create Build.PL from template
mb_version = 0.2808_01  ; version available in 5.10.0
[Manifest]              ; build MANIFEST file (do this last)

; verify and release the distribution
; XXX: disabled for now - testing would require installation
;[TestRelease]           ; run tests before releasing
[ConfirmRelease]        ; ask to confirm release/upload
[UploadToCPAN]          ; push it to CPAN
[Git::Push]             ; push everything to remote repository

libjio/libjio/check.c  view on Meta::CPAN

	if (rv == 0) {
		if (unlink(brokenname) != 0) {
			ret = J_EIO;
			goto exit;
		}
	} else if (errno != ENOENT) {
		ret = J_EIO;
		goto exit;
	}

	/* verify (and possibly fix) all the transactions */
	for (i = 1; i <= maxtid; i++) {
		curts = jtrans_new(&fs, 0);
		if (curts == NULL) {
			ret = J_ENOMEM;
			goto exit;
		}

		curts->id = i;

		/* open the transaction file, using i as its name, so we are

libjio/tests/behaviour/t_corruption.py  view on Meta::CPAN


	n = run_with_tmp(f1)
	assert content(n) == ''
	tc = open(transpath(n, 1)).read()
	# flip just one bit in the transaction data
	pos = DHS + DOHS + len(c) / 2
	tc = tc[:pos] + \
		chr((ord(tc[pos]) & 0xFE) | (~ ord(tc[pos]) & 0x1) & 0xFF) + \
		tc[pos + 1:]
	open(transpath(n, 1), 'w').write(tc)
	fsck_verify(n, corrupt = 1)
	assert content(n) == ''
	cleanup(n)

def test_c02():
	"truncate trans"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''
	tp = transpath(n, 1)
	open(tp, 'r+').truncate(len(content(tp)) - 2)
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c03():
	"op len too big"
	c = gencontent(10)

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''

	tf = TransFile(transpath(n, 1))
	tf.ops[0].tlen = 99
	tf.save()
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c04():
	"op len too small"
	c = gencontent(100)

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''

	tf = TransFile(transpath(n, 1))
	tf.ops[0].tlen = 10
	tf.save()
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c05():
	"truncate trans (tiny)"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''
	tp = transpath(n, 1)
	open(tp, 'r+').truncate(2)
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c06():
	"header version != 1"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''

	# there is no need to recalculate the checsum because it is verified
	# after the version check
	tf = TransFile(transpath(n, 1))
	tf.ver = 8
	tf.save()
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c07():
	"trailer numops mismatch"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''

	# there is no need to recalculate the checsum because it is verified
	# after the numops check
	tf = TransFile(transpath(n, 1))
	tf.numops = 55
	tf.save()
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_c08():
	"broken journal"
	c = gencontent()

	f, jf = bitmp(jflags = 0)
	n = f.name

libjio/tests/behaviour/t_corruption.py  view on Meta::CPAN


	def f2(f, jf):
		try:
			jf.pwrite(c, 200)
		except IOError:
			return
		raise RuntimeError

	run_forked(f2, f, jf)

	fsck_verify(n, reapplied = 1)
	assert content(n) == c
	assert not os.path.exists(jiodir(n) + '/broken')
	cleanup(n)

libjio/tests/behaviour/t_fi.py  view on Meta::CPAN

		jf.write(c)
		fiu.enable("jio/get_tid/overflow")
		try:
			jf.write(c)
		except IOError:
			pass

	n = run_with_tmp(f1)
	assert content(n) == c
	assert struct.unpack("I", content(jiodir(n) + '/lock'))[0] == 0
	fsck_verify(n)
	assert content(n) == c
	cleanup(n)

def test_f02():
	"fail jio/commit/created_tf"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/created_tf")
		jf.write(c)

	n = run_with_tmp(f1)
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_f03():
	"fail jio/commit/tf_header"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_header")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_f04():
	"fail jio/commit/tf_pre_addop"
	c = gencontent()

	def f1(f, jf):
		fiu.enable_external("jio/commit/tf_pre_addop",
				gen_ret_seq((0, 1)))
		t = jf.new_trans()
		t.add_w(c, 0)
		t.add_w(c, len(c) + 200)
		t.commit()

	n = run_with_tmp(f1)

	assert len(content(transpath(n, 1))) == DHS + DOHS + len(c)
	assert content(n) == ''
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_f05():
	"fail jio/commit/tf_opdata"
	c = gencontent()

	def f1(f, jf):
		fiu.enable_external("jio/commit/tf_opdata",
				gen_ret_seq((0, 1)))
		t = jf.new_trans()
		t.add_w(c, 0)
		t.add_w(c, len(c) + 200)
		t.commit()

	n = run_with_tmp(f1)

	assert len(content(transpath(n, 1))) == DHS + (DOHS + len(c)) * 2
	assert content(n) == ''
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_f06():
	"fail jio/commit/tf_data"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_data")
		t = jf.new_trans()
		t.add_w(c, 0)
		t.add_w(c, len(c) + 200)
		t.commit()

	n = run_with_tmp(f1)

	assert len(content(transpath(n, 1))) == DHS + (DOHS + len(c)) * 2
	assert content(n) == ''
	fsck_verify(n, broken = 1)
	assert content(n) == ''
	cleanup(n)

def test_f07():
	"fail jio/commit/tf_sync"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/tf_sync")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == ''
	fsck_verify(n, reapplied = 1)
	assert content(n) == c
	cleanup(n)

def test_f08():
	"fail jio/commit/wrote_op"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/wrote_op")
		t = jf.new_trans()
		t.add_w(c, 0)
		t.add_w(c, len(c) + 200)
		t.commit()

	n = run_with_tmp(f1)

	assert content(n) == c
	fsck_verify(n, reapplied = 1)
	assert content(n) == c + '\0' * 200 + c
	cleanup(n)

def test_f09():
	"fail jio/commit/wrote_all_ops"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/wrote_all_ops")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == c
	fsck_verify(n, reapplied = 1)
	assert content(n) == c
	cleanup(n)

def test_f10():
	"fail jio/commit/pre_ok_free_tid"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/commit/pre_ok_free_tid")
		jf.write(c)

	n = run_with_tmp(f1)
	assert content(n) == c
	assert struct.unpack("I", content(jiodir(n) + '/lock'))[0] == 1
	fsck_verify(n)
	assert content(n) == c
	assert not os.path.exists(jiodir(n))
	cleanup(n)

def test_f11():
	"fail jio/commit/tf_sync in rollback"
	c = gencontent()

	def f1(f, jf):
		jf.write('x' * (80 + len(c)))
		t = jf.new_trans()
		t.add_w(c, 80)
		t.commit()
		assert content(f.name) == 'x' * 80 + c
		fiu.enable("jio/commit/tf_sync")
		t.rollback()

	n = run_with_tmp(f1)

	assert content(n) == 'x' * 80 + c
	fsck_verify(n, reapplied = 1)
	assert content(n) == 'x' * (80 + len(c))
	cleanup(n)

def test_f12():
	"fail jio/jsync/pre_unlink"
	c = gencontent()

	def f1(f, jf):
		fiu.enable("jio/jsync/pre_unlink")
		t = jf.new_trans()
		t.add_w(c, 0)
		t.commit()
		jf.jsync()

	n = run_with_tmp(f1, libjio.J_LINGER)

	assert content(n) == c
	fsck_verify(n, reapplied = 1)
	assert content(n) == c
	cleanup(n)


libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

from tf import *


def test_n01():
	"open + close"
	def f1(f, jf):
		pass

	n = run_with_tmp(f1)
	assert content(n) == ''
	fsck_verify(n)
	assert content(n) == ''
	cleanup(n)

def test_n02():
	"write + seek + read"
	c = gencontent()

	def f1(f, jf):
		jf.write(c[:len(c) / 2])
		jf.write(c[len(c) / 2:])
		jf.lseek(0, 0)
		assert jf.read(len(c) * 2) == c

	n = run_with_tmp(f1)
	assert content(n) == c
	fsck_verify(n)
	cleanup(n)

def test_n03():
	"pwrite"
	c = gencontent()

	def f1(f, jf):
		jf.pwrite(c, 80)

	n = run_with_tmp(f1)
	assert content(n) == '\0' * 80 + c
	fsck_verify(n)
	cleanup(n)

def test_n04():
	"truncate"
	def f1(f, jf):
		jf.truncate(826)

	n = run_with_tmp(f1)
	assert content(n) == '\0' * 826
	fsck_verify(n)
	cleanup(n)

def test_n05():
	"commit"
	c = gencontent()

	def f1(f, jf):
		t = jf.new_trans()
		t.add_w(c, 80)
		t.commit()

	n = run_with_tmp(f1)
	assert content(n) == '\0' * 80 + c
	fsck_verify(n)
	cleanup(n)

def test_n06():
	"empty, then rollback"
	c = gencontent()

	def f1(f, jf):
		t = jf.new_trans()
		t.add_w(c, 80)
		t.commit()
		t.rollback()

	n = run_with_tmp(f1)

	# XXX: This is weird, because the file was empty at the beginning.
	# However, making it go back to 0 is delicate and the current code
	# doesn't implement it. It probably should.
	assert content(n) == '\0' * 80
	fsck_verify(n)
	cleanup(n)

def test_n07():
	"extending, then rollback"
	c1 = gencontent()
	c2 = gencontent()

	def f1(f, jf):
		jf.write(c1)
		t = jf.new_trans()
		t.add_w(c2, len(c1) - 973)
		t.commit()
		t.rollback()

	n = run_with_tmp(f1)

	assert content(n) == c1
	fsck_verify(n)
	cleanup(n)

def test_n08():
	"multiple overlapping ops"
	c1 = gencontent(9345)
	c2 = gencontent(len(c1))
	c3 = gencontent(len(c1))
	c4 = gencontent(len(c1))
	c5 = gencontent(len(c1))

libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

		jf.write(c1)
		t = jf.new_trans()
		t.add_w(c2, len(c1) - 973)
		t.add_w(c3, len(c1) - 1041)
		t.add_w(c4, len(c1) - 666)
		t.add_w(c5, len(c1) - 3000)
		t.commit()

	n = run_with_tmp(f1)
	assert content(n) == c1[:-3000] + c5 + c4[- (- 666 + 3000):]
	fsck_verify(n)
	cleanup(n)

def test_n09():
	"rollback multiple overlapping ops"
	c1 = gencontent(9345)
	c2 = gencontent(len(c1))
	c3 = gencontent(len(c1))
	c4 = gencontent(len(c1))
	c5 = gencontent(len(c1))

libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

		t.add_w(c2, len(c1) - 973)
		t.add_w(c3, len(c1) - 1041)
		t.add_w(c4, len(c1) - 666)
		t.add_w(c5, len(c1) - 3000)
		t.commit()
		t.rollback()

	n = run_with_tmp(f1)

	assert content(n) == c1
	fsck_verify(n)
	cleanup(n)

def test_n10():
	"lingering transactions"
	c = gencontent()

	def f1(f, jf):
		t = jf.new_trans()
		t.add_w(c, 0)
		t.commit()
		del t
		assert content(f.name) == c
		assert os.path.exists(transpath(f.name, 1))
		jf.jsync()
		assert not os.path.exists(transpath(f.name, 1))

	n = run_with_tmp(f1, libjio.J_LINGER)

	assert content(n) == c
	fsck_verify(n)
	cleanup(n)

def test_n11():
	"jfsck a nonexisting file"
	try:
		libjio.jfsck('this file does not exist')
	except IOError:
		return
	raise

libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

	"autosync"
	f, jf = bitmp(jflags = libjio.J_LINGER)
	n = f.name

	jf.autosync_start(1, 10)
	jf.write('x' * 200)
	jf.write('x' * 200)
	jf.autosync_stop()
	del jf

	fsck_verify(n)
	cleanup(n)

def test_n15():
	"jpread/jpwrite"
	c = gencontent()

	f, jf = bitmp(jflags = libjio.J_LINGER)
	n = f.name

	jf.pwrite(c, 2000)
	assert content(n) == '\0' * 2000 + c
	assert jf.pread(len(c), 2000) == c
	del jf

	fsck_verify(n)
	cleanup(n)

def test_n16():
	"jopen r/o + jtrans_add_w + jtrans_commit"
	c = gencontent()

	# create the file before opening, read-only mode does not create it
	n = tmppath()
	open(n, 'w+')
	f, jf = biopen(n, mode = 'r')

libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

	t.add_w(c, 80)
	t.commit()
	try:
		t.rollback()
	except IOError:
		pass
	else:
		raise AssertionError

	assert content(n) == '\0' * 80 + c
	fsck_verify(n)
	cleanup(n)

def test_n19():
	"jwrite in files opened with O_APPEND"
	c1 = gencontent()
	c2 = gencontent()
	f, jf = bitmp(mode = 'a')
	n = f.name

	jf.write(c1)
	jf.write(c2)

	assert content(n) == c1 + c2
	fsck_verify(n)
	cleanup(n)

def test_n20():
	"jtrans_add_w of 0 length"
	f, jf = bitmp()
	n = f.name

	t = jf.new_trans()

	try:
		t.add_w('', 80)
	except IOError:
		pass
	else:
		raise AssertionError

	del t
	del jf
	fsck_verify(n)
	cleanup(n)

def test_n21():
	"jwritev and jreadv"
	f, jf = bitmp()
	n = f.name

	jf.writev(["hello ", "world"])
	l = [bytearray("......"), bytearray(".....")]
	jf.lseek(0, 0)
	jf.readv(l)

	assert content(n) == "hello world"
	assert l[0] == "hello " and l[1] == "world"
	fsck_verify(n)
	cleanup(n)

def test_n22():
	"jpread/jpwrite ~2mb"
	c = gencontent(2 * 1024 * 1024 + 1465)

	f, jf = bitmp(jflags = libjio.J_LINGER)
	n = f.name

	jf.pwrite(c, 2000)
	assert content(n) == '\0' * 2000 + c
	assert jf.pread(len(c), 2000) == c
	del jf

	fsck_verify(n)
	cleanup(n)

def test_n23():
	"jtrans_add_w + jtrans_add_r"
	f, jf = bitmp()
	n = f.name

	c1 = gencontent(1000)
	c2 = gencontent(1000)
	c3 = gencontent(1000)

libjio/tests/behaviour/t_normal.py  view on Meta::CPAN

	t.add_r(buf2, len(c1) - len(buf2) / 2)
	t.add_w(c3, len(c1) + len(c2))
	t.commit()

	assert content(n) == c1 + c2 + c3
	assert buf1 == c1[:len(buf1)]
	assert buf2 == c1[-(len(buf2) / 2):] + c2[:len(buf2) / 2]

	del t
	del jf
	fsck_verify(n)
	cleanup(n)


libjio/tests/behaviour/tf.py  view on Meta::CPAN


def transpath(path, ntrans):
	jpath = jiodir(path)
	return jpath + '/' + str(ntrans)

def fsck(path, flags = 0):
	"Calls libjio's jfsck()."
	res = libjio.jfsck(path, flags = flags)
	return res

def fsck_verify(n, **kwargs):
	"""Runs fsck(n), and verifies that the fsck result matches the given
	values. The default is to match all elements except total to 0 (total
	is calculated automatically from the sum of the others). Raises an
	AssertionError if the given results were not the ones expected."""
	expected = {
		'invalid': 0,
		'broken': 0,
		'reapplied': 0,
		'corrupt': 0,
		'in_progress': 0,

libjio/tests/stress/jiostress  view on Meta::CPAN

	def unlock(self, start, end):
		#print(os.getpid(), '\tunlock:', start, end)
		#sys.stdout.flush()
		fcntl.lockf(self.fd, fcntl.LOCK_UN, end - start, start)


#
# A range of bytes inside a file, used inside the transactions
#
# Note it can't "remember" the fd as it may change between prepare() and
# verify().
#

class Range:
	def __init__(self, fsize, maxlen, lockmgr):
		# public
		self.start, self.end = randfrange(fsize, maxlen)
		self.new_data = None
		self.type = 'r'

		# private

libjio/tests/stress/jiostress  view on Meta::CPAN

		   (self.ext_start <= other.ext_end <= self.ext_end):
			return True
		return False

	def prepare_r(self):
		self.type = 'r'
		self.read_buf = bytearray(self.end - self.start)
		self.lockmgr.lock(self.ext_start, self.ext_end)
		self.locked = True

	def verify_r(self, fd):
		real_data = pread(fd, self.start, self.end)
		if real_data != self.read_buf:
			print('Corruption detected')
			self.show(fd)
			raise ConsistencyError

	def prepare_w(self, fd):
		self.type = 'w'
		self.lockmgr.lock(self.ext_start, self.ext_end)
		self.locked = True

libjio/tests/stress/jiostress  view on Meta::CPAN

		self.prev_data = pread(fd, self.ext_start, self.ext_end)

		self.new_data = getbytes(self.end - self.start)
		self.new_data_ctx = \
			self.prev_data[:self.start - self.ext_start] \
			+ self.new_data \
			+ self.prev_data[- (self.ext_end - self.end):]

		return self.new_data, self.start

	def verify_w(self, fd):
		# NOTE: fd must be a real file
		real_data = pread(fd, self.ext_start, self.ext_end)
		if real_data not in (self.prev_data, self.new_data_ctx):
			print('Corruption detected')
			self.show(fd)
			raise ConsistencyError

	def verify(self, fd):
		if self.type == 'r':
			self.verify_r(fd)
		else:
			self.verify_w(fd)

	def show(self, fd):
		real_data = pread(fd, self.start, self.end)
		print('Range:', self.ext_start, self.ext_end)
		print('Real:', comp_cont(real_data))
		if self.type == 'w':
			print('Prev:', comp_cont(self.prev_data))
			print('New: ', comp_cont(self.new_data_ctx))
		else:
			print('Buf:', comp_cont(self.read_buf))
		print()


#
# Transactions
#

class T_base:
	"Interface for the transaction types"
	def __init__(self, f, jf, fsize, lockmgr, do_verify):
		pass

	def prepare(self):
		pass

	def apply(self):
		pass

	def verify(self, write_only = False):
		pass

class T_jwrite (T_base):
	def __init__(self, f, jf, fsize, lockmgr, do_verify):
		self.f = f
		self.jf = jf
		self.fsize = fsize
		self.do_verify = do_verify

		self.maxoplen = min(int(fsize / 256), 2 * 1024 * 1024)
		self.range = Range(self.fsize, self.maxoplen, lockmgr)

	def prepare(self):
		self.range.prepare_w(self.f)

	def apply(self):
		self.jf.pwrite(self.range.new_data, self.range.start)

	def verify(self, write_only = False):
		if not self.do_verify:
			return
		self.range.verify(self.f)

class T_writeonly (T_base):
	def __init__(self, f, jf, fsize, lockmgr, do_verify):
		self.f = f
		self.jf = jf
		self.fsize = fsize
		self.do_verify = do_verify

		# favour many small ops
		self.maxoplen = 512 * 1024
		self.nops = random.randint(1, 26)

		self.ranges = []

		c = 0
		while len(self.ranges) < self.nops and c < self.nops * 1.25:
			candidate = Range(self.fsize, self.maxoplen, lockmgr)

libjio/tests/stress/jiostress  view on Meta::CPAN

	def prepare(self):
		for r in self.ranges:
			r.prepare_w(self.f)

	def apply(self):
		t = self.jf.new_trans()
		for r in self.ranges:
			t.add_w(r.new_data, r.start)
		t.commit()

	def verify(self, write_only = False):
		if not self.do_verify:
			return

		try:
			for r in self.ranges:
				r.verify(self.f)
		except ConsistencyError:
			# show context on errors
			print("-" * 50)
			for r in self.ranges:
				r.show(self.f)
			print("-" * 50)
			raise

class T_readwrite (T_writeonly):
	def __init__(self, f, jf, fsize, lockmgr, do_verify):
		T_writeonly.__init__(self, f, jf, fsize, lockmgr, do_verify)
		self.read_ranges = []

	def prepare(self):
		for r in self.ranges:
			if random.choice((True, False)):
				r.prepare_w(self.f)
			else:
				r.prepare_r()

	def apply(self):
		t = self.jf.new_trans()
		for r in self.ranges:
			if r.type == 'r':
				t.add_r(r.read_buf, r.start)
			else:
				t.add_w(r.new_data, r.start)
		t.commit()

	def verify(self, write_only = False):
		if not self.do_verify:
			return

		try:
			for r in self.ranges:
				if write_only and r.type == 'r':
					continue
				r.verify(self.f)
		except ConsistencyError:
			# show context on errors
			print("-" * 50)
			for r in self.ranges:
				r.show(self.f)
			print("-" * 50)
			raise

t_list = [T_jwrite, T_writeonly, T_readwrite]


#
# The test itself
#

class Stresser:
	def __init__(self, fname, fsize, nops, use_fi, use_as, output,
			lockmgr, do_verify):
		self.fname = fname
		self.fsize = fsize
		self.nops = nops
		self.use_fi = use_fi
		self.use_as = use_as
		self.output = output
		self.lockmgr = lockmgr
		self.do_verify = do_verify

		jflags = 0
		if use_as:
			jflags = libjio.J_LINGER

		self.jf = libjio.open(fname, libjio.O_RDWR | libjio.O_CREAT,
				0o600, jflags)
		self.f = open(fname, mode = 'rb')

		self.jf.truncate(fsize)

		if use_as:
			self.jf.autosync_start(5, 10 * 1024 * 1024)

	def apply(self, trans):
		trans.prepare()
		trans.apply()
		trans.verify()
		return True

	def apply_fork(self, trans):
		# do the prep before the fork so we can verify() afterwards
		trans.prepare()

		sys.stdout.flush()
		pid = os.fork()
		if pid == 0:
			# child
			try:
				self.fiu_enable()
				trans.apply()
				self.fiu_disable()

libjio/tests/stress/jiostress  view on Meta::CPAN

					traceback.print_exc()
				self.fiu_disable()
				sys.exit(1)
			except MemoryError:
				self.fiu_disable()
				sys.exit(1)
			except:
				self.fiu_disable()
				traceback.print_exc()
				sys.exit(1)
			trans.verify()
			sys.exit(0)
		else:
			# parent
			id, status = os.waitpid(pid, 0)
			if not os.WIFEXITED(status):
				i = (status,
					os.WIFSIGNALED(status),
					os.WTERMSIG(status))
				raise RuntimeError(i)

			if os.WEXITSTATUS(status) != 0:
				return False
			return True

	def reopen(self, trans):
		self.jf = None
		r = jfsck(self.fname)

		trans.verify(write_only = True)

		self.jf = libjio.open(self.fname,
			libjio.O_RDWR | libjio.O_CREAT, 0o600)
		return r

	def fiu_enable(self):
		if not self.use_fi:
			return

		# To improve code coverage, we randomize the probability each

libjio/tests/stress/jiostress  view on Meta::CPAN

			fiu.disable('posix/*')
			fiu.disable('jio/*')
			fiu.disable('linux/*')

	def run(self):
		nfailures = 0

		for i in range(1, self.nops + 1):
			trans = random.choice(t_list)(self.f, self.jf,
					self.fsize, self.lockmgr,
					self.do_verify)

			if self.use_fi:
				r = self.apply_fork(trans)
			else:
				r = self.apply(trans)

			if r:
				self.output.feed(success = True)
			else:
				self.output.feed(success = False)
				nfailures += 1
				r = self.reopen(trans)
				trans.verify(write_only = True)

		return nfailures


#
# Main
#

def run_stressers(nproc, fname, fsize, nops, use_fi, use_as, output, lockmgr,
		do_verify):
	pids = []
	print("Launching stress test")
	for i in range(nproc):
		# Calculate how many operations will this child perform. The
		# last one will work a little more so we get exactly nops.
		# Note we prefer to work extra in the end rather than having
		# the last process with 0 child_nops, that's why we use int()
		# instead of round() or ceil().
		child_nops = int(nops / nproc)
		if i == nproc - 1:
			child_nops = nops - int(nops / nproc) * i

		output.prefork()
		sys.stdout.flush()
		pid = os.fork()
		if pid == 0:
			# child
			output.child()
			s = Stresser(fname, fsize, child_nops, use_fi, use_as,
					output, lockmgr, do_verify)
			s.run()
			sys.exit(0)
		else:
			output.parent()
			pids.append(pid)

	print("Launched stress tests")
	totalops, nfailures = output.output_loop()
	print("Stress test completed, waiting for children")
	nerrors = 0

libjio/tests/stress/jiostress  view on Meta::CPAN

	parser.add_option("", "--fi", dest = "use_fi",
		action = "store_true", default = False,
		help = "use fault injection (conflicts with --as and -p > 1)")
	parser.add_option("", "--as", dest = "use_as",
		action = "store_true", default = False,
		help = "use J_LINGER + autosync (conflicts with --fi)")
	parser.add_option("", "--no-internal-lock",
		dest = "use_internal_locks", action = "store_false",
		default = True,
		help = "do not lock internally, disables verification")
	parser.add_option("", "--no-verify", dest = "do_verify",
		action = "store_false", default = True,
		help = "do not perform verifications")
	parser.add_option("", "--keep", dest = "keep",
		action = "store_true", default = False,
		help = "keep the file after completing the test")
	parser.add_option("", "--force", dest = "force",
		action = "store_true", default = False,
		help = "force the tests to run, even if conflicting"
			+ " options are selected")

libjio/tests/stress/jiostress  view on Meta::CPAN

	if not options.force:
		if options.use_fi and options.use_as:
			print("Error: --fi and --as cannot be used together")
			return 1

		if options.use_fi and options.nproc > 1:
			print("Error: --fi cannot be used with multiple processes")
			return 1

	if not options.use_internal_locks:
		options.do_verify = False

	output = OutputHandler(every = 2)
	if options.use_internal_locks:
		lockmgr = LockManager()
	else:
		lockmgr = VoidLockManager()

	success = run_stressers(options.nproc, fname, fsize, options.nops,
			options.use_fi, options.use_as, output, lockmgr,
			options.do_verify)

	r = jfsck(fname)
	print("Final check completed")
	if success and not options.keep:
		jfsck(fname, cleanup = True)
		os.unlink(fname)

	if not success:
		print("Test failed")
		return 1



( run in 0.499 second using v1.01-cache-2.11-cpan-5467b0d2c73 )