summaryrefslogtreecommitdiffstats
path: root/xlators/features/glupy/src/negative.py
blob: 6ca855f72f0ba1ea38e490232845682a4d32d5e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import sys
from gluster import *

# Negative-lookup-caching example.  If a file wasn't there the last time we
# looked, it's probably still not there.  This translator keeps track of
# those failed lookups for us, and returns ENOENT without needing to pass the
# call any further for repeated requests.

# If we were doing this for real, we'd need separate caches for each xlator
# instance.  The easiest way to do this would be to have xlator.__init__
# "register" each instance in a module-global dict, with the key as the C
# translator address and the value as the xlator object itself.  For testing
# and teaching, it's sufficient just to have one cache.  The keys are parent
# GFIDs, and the entries are lists of names within that parent that we know
# don't exist.
cache = {}

# TBD: we need a better way of handling per-request data (frame->local in C).
dl.get_id.restype = c_long
dl.get_id.argtypes = [ POINTER(call_frame_t) ]

def uuid2str (orig):
	return "%08x%08x%08x%08x" % (orig[0], orig[1], orig[2], orig[3])

class xlator (Translator):

	def __init__ (self, c_this):
		self.requests = {}
		Translator.__init__(self,c_this)

	def lookup_fop (self, frame, this, loc, xdata):
		pargfid = uuid2str(loc.contents.pargfid)
		print "lookup FOP: %s:%s" % (pargfid, loc.contents.name)
		# Check the cache.
		if cache.has_key(pargfid):
			if loc.contents.name in cache[pargfid]:
				print "short-circuiting for %s:%s" % (
					pargfid, loc.contents.name)
				dl.unwind_lookup(frame,0,this,-1,2,None,None,
						 None,None)
				return 0
		key = dl.get_id(frame)
		self.requests[key] = (pargfid, loc.contents.name[:])
		# TBD: get real child xl from init, pass it here
		dl.wind_lookup(frame,POINTER(xlator_t)(),loc,xdata)
		return 0

	def lookup_cbk (self, frame, cookie, this, op_ret, op_errno, inode, buf,
			xdata, postparent):
		print "lookup CBK: %d (%d)" % (op_ret, op_errno)
		key = dl.get_id(frame)
		pargfid, name = self.requests[key]
		# Update the cache.
		if op_ret == 0:
			print "found %s, removing from cache" % name
			if cache.has_key(pargfid):
				cache[pargfid].discard(name)
		elif op_errno == 2:	# ENOENT
			print "failed to find %s, adding to cache" % name
			if cache.has_key(pargfid):
				cache[pargfid].add(name)
			else:
				cache[pargfid] = set([name])
		del self.requests[key]
		dl.unwind_lookup(frame,cookie,this,op_ret,op_errno,
						 inode,buf,xdata,postparent)
		return 0

	def create_fop (self, frame, this, loc, flags, mode, umask, fd, xdata):
		pargfid = uuid2str(loc.contents.pargfid)
		print "create FOP: %s:%s" % (pargfid, loc.contents.name)
		key = dl.get_id(frame)
		self.requests[key] = (pargfid, loc.contents.name[:])
		# TBD: get real child xl from init, pass it here
		dl.wind_create(frame,POINTER(xlator_t)(),loc,flags,mode,umask,
			       fd,xdata)
		return 0

	def create_cbk (self, frame, cookie, this, op_ret, op_errno, fd, inode,
			buf, preparent, postparent, xdata):
		print "create CBK: %d (%d)" % (op_ret, op_errno)
		key = dl.get_id(frame)
		pargfid, name = self.requests[key]
		# Update the cache.
		if op_ret == 0:
			print "created %s, removing from cache" % name
			if cache.has_key(pargfid):
				cache[pargfid].discard(name)
		del self.requests[key]
		dl.unwind_create(frame,cookie,this,op_ret,op_errno,fd,inode,buf,
				 preparent,postparent,xdata)
		return 0