Skip to content

Commit

Permalink
py9p: rewrite read/write routines
Browse files Browse the repository at this point in the history
 * thread safe: each read/write cycle should be done sequentially
 * flush directory cache entry on write ('cause size changes)
 * use per-Fid() iounit + default iounit for fidcache
  • Loading branch information
svinota committed Dec 16, 2012
1 parent 84feacd commit 31922de
Showing 1 changed file with 35 additions and 16 deletions.
51 changes: 35 additions & 16 deletions py9p/fuse9p.py
Expand Up @@ -38,6 +38,7 @@
MIN_FID = 1024
MAX_FID = 65535
MAX_RECONNECT_INTERVAL = 1024
IOUNIT = 1024 * 16

rpccodes = {
"duplicate fid": -errno.EBADFD,
Expand Down Expand Up @@ -145,6 +146,7 @@ def __init__(self, start=MIN_FID, limit=MAX_FID):
dict.__init__(self)
self.start = start
self.limit = limit
self.iounit = IOUNIT
self.fids = list(range(self.start, self.limit + 1))

def acquire(self):
Expand All @@ -153,7 +155,7 @@ def acquire(self):
"""
if len(self.fids) < 1:
raise NoFidError()
return Fid(self.fids.pop(0))
return Fid(self.fids.pop(0), self.iounit)

def release(self, f):
"""
Expand All @@ -172,8 +174,9 @@ class Fid(object):
See: write(), read(), release()
"""
def __init__(self, fid):
def __init__(self, fid, iounit=IOUNIT):
self.fid = fid
self.iounit = iounit


class ClientFS(fuse.Fuse):
Expand All @@ -198,12 +201,14 @@ def __init__(self, address, credentials, mountpoint,
self.credentials = credentials
self.debug = debug
self.timeout = timeout
self.msize = 1024 * 16
self.msize = IOUNIT
self.sock = None
self.exit = None
self.dotu = 1
self.keep_reconnect = keep_reconnect
self._lock = threading.Lock()
self._rlock = threading.Lock()
self._wlock = threading.Lock()
self._interval = 1
self._reconnect_event = threading.Event()
self._connected_event = threading.Event()
Expand Down Expand Up @@ -288,6 +293,7 @@ def _reconnect_target(self, init=False, dotu=1):
credentials=self.credentials,
dotu=dotu, msize=self.msize)
self.msize = self.client.msize
self.fidcache.iounit = self.client.msize - py9p.IOHDRSZ
self._connected_event.set()
self._lock.release()
return
Expand Down Expand Up @@ -325,7 +331,8 @@ def open(self, tfid, path, mode):
try:
self.client._walk(self.client.ROOT,
f.fid, filter(None, path.split("/")))
self.client._open(f.fid, py9p.open2plan(mode))
fcall = self.client._open(f.fid, py9p.open2plan(mode))
f.iounit = fcall.iounit
return f
except:
self.fidcache.release(f)
Expand Down Expand Up @@ -440,21 +447,33 @@ def truncate(self, tfid, path, size):

@guard
def write(self, tfid, path, buf, offset, f):
l = len(buf)
for i in range(l / self.msize + 1):
start = i * self.msize
length = self.msize + min(0, (l - ((i + 1) * self.msize)))
self.client._write(f.fid, offset + start, buf[start:length])
return l
if py9p.hash8(path) in self.dircache:
del self.dircache[py9p.hash8(path)]
with self._wlock:
size = len(buf)
for i in range((size + f.iounit - 1) / f.iounit):
start = i * f.iounit
length = start + f.iounit
self.client._write(f.fid, offset + start,
buf[start:length])
return size

@guard
def read(self, tfid, path, size, offset, f):
data = bytes()
for i in range(size / self.msize + 1):
ret = self.client._read(f.fid, offset, self.msize)
data += ret.data
offset += len(ret.data)
return data[:size]
with self._rlock:
data = bytes()
i = 0
while True:
# we do not rely nor on msize, neither on iounit,
# so, shift offset only with real data read
ret = self.client._read(f.fid, offset,
min(size - len(data), f.iounit))
data += ret.data
offset += len(ret.data)
if size <= len(data) or len(ret.data) == 0:
break
i += 1
return data[:size]

@guard
def rename(self, tfid, path, dest):
Expand Down

0 comments on commit 31922de

Please sign in to comment.