import os, sys, time, errno, threading
from fuse import FUSE, Operations
root, mount, signal = sys.argv[1:]
active = 0
draining = False
def drain():
 global draining
 with open(signal + ".drain") as control: control.read()
 draining = True
 if active == 0: print('DRAINED', flush=True)
os.mkfifo(signal + ".drain")
threading.Thread(target=drain, daemon=True).start()
class Slow(Operations):
 def init(self,p): print('READY',flush=True)
 def full(self,p): return root+p
 def getattr(self,p,fh=None):
  s=os.lstat(self.full(p)); return {k:getattr(s,k) for k in ('st_atime','st_ctime','st_gid','st_mode','st_mtime','st_nlink','st_size','st_uid')}
 def readdir(self,p,fh): return ['.','..']+os.listdir(self.full(p))
 def open(self,p,flags): return os.open(self.full(p),flags)
 def read(self,p,size,offset,fh):
  global active
  delayed = 'slow' in p and not draining
  if delayed:
   active += 1
   with open(signal,'a') as f: f.write('reading\n'); f.flush()
   time.sleep(40)
  result = os.pread(fh,size,offset)
  if delayed:
   active -= 1
   if draining and active == 0: print('DRAINED', flush=True)
  return result
 def release(self,p,fh): os.close(fh); return 0
 def create(self,p,mode,fi=None): return os.open(self.full(p),os.O_WRONLY|os.O_CREAT,mode)
 def write(self,p,data,offset,fh): return os.pwrite(fh,data,offset)
 def truncate(self,p,length,fh=None):
  with open(self.full(p),'r+b') as f:f.truncate(length)
 def flush(self,p,fh): return 0
 def fsync(self,p,datasync,fh): return 0
 def access(self,p,mode): return 0
 def readlink(self,p):return os.readlink(self.full(p))
FUSE(Slow(),mount,foreground=True,nothreads=False,nonempty=True)
