def ExecFlock(self, lockfile, *cmd_list):
"""Emulates the most basic behavior of Linux's flock(1)."""
# Rely on exception handling to report errors.
# Note that the stock python on SunOS has a bug
# where fcntl.flock(fd, LOCK_EX) always fails
# with EBADF, that's why we use this F_SETLK
# hack instead.
fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
if sys.platform.startswith('aix'):
# Python on AIX is compiled with LARGEFILE support, which changes the
# struct size.
op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
else:
op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
fcntl.fcntl(fd, fcntl.F_SETLK, op)
return subprocess.call(cmd_list)
python类F_WRLCK的实例源码
def ExecFlock(self, lockfile, *cmd_list):
"""Emulates the most basic behavior of Linux's flock(1)."""
# Rely on exception handling to report errors.
# Note that the stock python on SunOS has a bug
# where fcntl.flock(fd, LOCK_EX) always fails
# with EBADF, that's why we use this F_SETLK
# hack instead.
fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
if sys.platform.startswith('aix'):
# Python on AIX is compiled with LARGEFILE support, which changes the
# struct size.
op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
else:
op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
fcntl.fcntl(fd, fcntl.F_SETLK, op)
return subprocess.call(cmd_list)
def ExecFlock(self, lockfile, *cmd_list):
"""Emulates the most basic behavior of Linux's flock(1)."""
# Rely on exception handling to report errors.
# Note that the stock python on SunOS has a bug
# where fcntl.flock(fd, LOCK_EX) always fails
# with EBADF, that's why we use this F_SETLK
# hack instead.
fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
if sys.platform.startswith('aix'):
# Python on AIX is compiled with LARGEFILE support, which changes the
# struct size.
op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
else:
op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
fcntl.fcntl(fd, fcntl.F_SETLK, op)
return subprocess.call(cmd_list)
def _getlock(self, name, fd, lock_type=None, offset=0, length=0, lock=None, tlock=False):
"""Get byte range lock on file given by file descriptor"""
rn = self.random.randint(0,9999)
stype = fcntl.F_SETLK
if lock_type == fcntl.F_UNLCK:
lstr = "UNLOCK"
if not lock or rn >= 100*self.unlock:
# Do not unlock file
return
self.nunlock += 1
else:
if tlock:
# Just do TLOCK
lstr = "TLOCK "
stype = fcntl.F_GETLK
if rn >= 100*self.tlock:
# No lock, so no tlock
return
self.ntlock += 1
else:
lstr = "LOCK "
if rn >= 100*self.lock:
# No lock
return
self.nlock += 1
if lock_type is None:
# Choose lock: read or write
if self._percent(50):
lock_type = fcntl.F_RDLCK
else:
lock_type = fcntl.F_WRLCK
if not tlock:
# LOCK is requested, but do TLOCK before actual lock
self._getlock(name, fd, lock_type=lock_type, offset=offset, length=length, lock=lock, tlock=True)
fstr = ""
if offset == 0 and length == 0 and lstr == "LOCK ":
fstr = " full file"
self._dprint("DBG4", "%s %s %d @ %d (%s)%s" % (lstr, name, length, offset, LOCKMAP[lock_type], fstr))
lockdata = struct.pack('hhllhh', lock_type, 0, offset, length, 0, 0)
return fcntl.fcntl(fd, stype, lockdata)
def lock(self, cmd, owner, **kw):
#return -EROFS
# The code here is much rather just a demonstration of the locking
# API than something which actually was seen to be useful.
# Advisory file locking is pretty messy in Unix, and the Python
# interface to this doesn't make it better.
# We can't do fcntl(2)/F_GETLK from Python in a platfrom independent
# way. The following implementation *might* work under Linux.
#
# if cmd == fcntl.F_GETLK:
# import struct
#
# lockdata = struct.pack('hhQQi', kw['l_type'], os.SEEK_SET,
# kw['l_start'], kw['l_len'], kw['l_pid'])
# ld2 = fcntl.fcntl(self.fd, fcntl.F_GETLK, lockdata)
# flockfields = ('l_type', 'l_whence', 'l_start', 'l_len', 'l_pid')
# uld2 = struct.unpack('hhQQi', ld2)
# res = {}
# for i in xrange(len(uld2)):
# res[flockfields[i]] = uld2[i]
#
# return fuse.Flock(**res)
# Convert fcntl-ish lock parameters to Python's weird
# lockf(3)/flock(2) medley locking API...
op = { fcntl.F_UNLCK : fcntl.LOCK_UN,
fcntl.F_RDLCK : fcntl.LOCK_SH,
fcntl.F_WRLCK : fcntl.LOCK_EX }[kw['l_type']]
if cmd == fcntl.F_GETLK:
return -EOPNOTSUPP
elif cmd == fcntl.F_SETLK:
if op != fcntl.LOCK_UN:
op |= fcntl.LOCK_NB
elif cmd == fcntl.F_SETLKW:
pass
else:
return -EINVAL
fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len'])
def lock_files(self, lock_type=None, offset=0, length=0):
"""Lock all files opened by open_files()."""
if lock_type is None:
lock_type = self.lock_type
ret = []
mode_str = 'WRITE' if lock_type == fcntl.F_WRLCK else 'READ'
lockdata = struct.pack('hhllhh', lock_type, 0, long(offset), long(length), 0, 0)
for fd in self.rfds + self.wfds:
try:
self.dprint('DBG3', "Lock file F_SETLKW (%s)" % mode_str)
rv = fcntl.fcntl(fd, fcntl.F_SETLKW, lockdata)
ret.append(rv)
except Exception, e:
self.warning("Unable to get lock on file: %r" % e)
return ret
def _do_io(self, **kwargs):
"""Read or write to the given file descriptor"""
fd = kwargs.pop("fd", None)
write = kwargs.pop("write", False)
offset = kwargs.pop("offset", 0)
size = kwargs.pop("size", 0)
fileobj = kwargs.pop("fileobj", None)
lockfull = kwargs.pop("lockfull", True)
lockout = None
if self.iodelay > 0.0:
time.sleep(self.iodelay)
# Set file offset to read/write
os.lseek(fd, offset, os.SEEK_SET)
if write:
if self.random and not lockfull:
# Lock file segment
lockout = self._getlock(fileobj.name, fd, lock_type=fcntl.F_WRLCK, offset=offset, length=size)
data = 'x' * size
self._dprint("DBG5", "WRITE %s %d @ %d" % (fileobj.name, size, offset))
if self.direct:
# Direct I/O -- use native write function
count = self.libc.write(fd, self.wbuffer, size)
else:
# Buffered I/O
count = os.write(fd, data)
if self._percent(self.fsync):
self._dprint("DBG4", "FSYNC %s" % fileobj.name)
self.nfsync += 1
os.fsync(fd)
self.nwrite += 1
self.wbytes += count
fsize = offset + count
if fileobj.size < fsize:
fileobj.size = fsize
else:
if self.random and not lockfull:
# Lock file segment
lockout = self._getlock(fileobj.name, fd, lock_type=fcntl.F_RDLCK, offset=offset, length=size)
self._dprint("DBG5", "READ %s %d @ %d" % (fileobj.name, size, offset))
if self.direct:
# Direct I/O -- use native read function
count = self.libc.read(fd, self.rbuffer, size)
else:
# Buffered I/O
data = os.read(fd, size)
count = len(data)
self.rbytes += count
self.nread += 1
if self.random and not lockfull:
# Unlock file segment
self._getlock(fileobj.name, fd, lock_type=fcntl.F_UNLCK, offset=offset, length=size, lock=lockout)
return count