##// END OF EJS Templates
tests: use baseurl instead of advertisedbaseurl...
Gregory Szorc -
r40206:f7ff5b4f default
parent child Browse files
Show More
@@ -1,193 +1,193
1 # wireprotosimplecache.py - Extension providing in-memory wire protocol cache
1 # wireprotosimplecache.py - Extension providing in-memory wire protocol cache
2 #
2 #
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from mercurial import (
10 from mercurial import (
11 extensions,
11 extensions,
12 registrar,
12 registrar,
13 repository,
13 repository,
14 util,
14 util,
15 wireprotoserver,
15 wireprotoserver,
16 wireprototypes,
16 wireprototypes,
17 wireprotov2server,
17 wireprotov2server,
18 )
18 )
19 from mercurial.utils import (
19 from mercurial.utils import (
20 interfaceutil,
20 interfaceutil,
21 stringutil,
21 stringutil,
22 )
22 )
23
23
24 CACHE = None
24 CACHE = None
25
25
26 configtable = {}
26 configtable = {}
27 configitem = registrar.configitem(configtable)
27 configitem = registrar.configitem(configtable)
28
28
29 configitem('simplecache', 'cacheapi',
29 configitem('simplecache', 'cacheapi',
30 default=False)
30 default=False)
31 configitem('simplecache', 'cacheobjects',
31 configitem('simplecache', 'cacheobjects',
32 default=False)
32 default=False)
33 configitem('simplecache', 'redirectsfile',
33 configitem('simplecache', 'redirectsfile',
34 default=None)
34 default=None)
35
35
36 # API handler that makes cached keys available.
36 # API handler that makes cached keys available.
37 def handlecacherequest(rctx, req, res, checkperm, urlparts):
37 def handlecacherequest(rctx, req, res, checkperm, urlparts):
38 if rctx.repo.ui.configbool('simplecache', 'cacheobjects'):
38 if rctx.repo.ui.configbool('simplecache', 'cacheobjects'):
39 res.status = b'500 Internal Server Error'
39 res.status = b'500 Internal Server Error'
40 res.setbodybytes(b'cacheobjects not supported for api server')
40 res.setbodybytes(b'cacheobjects not supported for api server')
41 return
41 return
42
42
43 if not urlparts:
43 if not urlparts:
44 res.status = b'200 OK'
44 res.status = b'200 OK'
45 res.headers[b'Content-Type'] = b'text/plain'
45 res.headers[b'Content-Type'] = b'text/plain'
46 res.setbodybytes(b'simple cache server')
46 res.setbodybytes(b'simple cache server')
47 return
47 return
48
48
49 key = b'/'.join(urlparts)
49 key = b'/'.join(urlparts)
50
50
51 if key not in CACHE:
51 if key not in CACHE:
52 res.status = b'404 Not Found'
52 res.status = b'404 Not Found'
53 res.headers[b'Content-Type'] = b'text/plain'
53 res.headers[b'Content-Type'] = b'text/plain'
54 res.setbodybytes(b'key not found in cache')
54 res.setbodybytes(b'key not found in cache')
55 return
55 return
56
56
57 res.status = b'200 OK'
57 res.status = b'200 OK'
58 res.headers[b'Content-Type'] = b'application/mercurial-cbor'
58 res.headers[b'Content-Type'] = b'application/mercurial-cbor'
59 res.setbodybytes(CACHE[key])
59 res.setbodybytes(CACHE[key])
60
60
61 def cachedescriptor(req, repo):
61 def cachedescriptor(req, repo):
62 return {}
62 return {}
63
63
64 wireprotoserver.API_HANDLERS[b'simplecache'] = {
64 wireprotoserver.API_HANDLERS[b'simplecache'] = {
65 'config': (b'simplecache', b'cacheapi'),
65 'config': (b'simplecache', b'cacheapi'),
66 'handler': handlecacherequest,
66 'handler': handlecacherequest,
67 'apidescriptor': cachedescriptor,
67 'apidescriptor': cachedescriptor,
68 }
68 }
69
69
70 @interfaceutil.implementer(repository.iwireprotocolcommandcacher)
70 @interfaceutil.implementer(repository.iwireprotocolcommandcacher)
71 class memorycacher(object):
71 class memorycacher(object):
72 def __init__(self, ui, command, encodefn, redirecttargets, redirecthashes,
72 def __init__(self, ui, command, encodefn, redirecttargets, redirecthashes,
73 req):
73 req):
74 self.ui = ui
74 self.ui = ui
75 self.encodefn = encodefn
75 self.encodefn = encodefn
76 self.redirecttargets = redirecttargets
76 self.redirecttargets = redirecttargets
77 self.redirecthashes = redirecthashes
77 self.redirecthashes = redirecthashes
78 self.req = req
78 self.req = req
79 self.key = None
79 self.key = None
80 self.cacheobjects = ui.configbool('simplecache', 'cacheobjects')
80 self.cacheobjects = ui.configbool('simplecache', 'cacheobjects')
81 self.cacheapi = ui.configbool('simplecache', 'cacheapi')
81 self.cacheapi = ui.configbool('simplecache', 'cacheapi')
82 self.buffered = []
82 self.buffered = []
83
83
84 ui.log('simplecache', 'cacher constructed for %s\n', command)
84 ui.log('simplecache', 'cacher constructed for %s\n', command)
85
85
86 def __enter__(self):
86 def __enter__(self):
87 return self
87 return self
88
88
89 def __exit__(self, exctype, excvalue, exctb):
89 def __exit__(self, exctype, excvalue, exctb):
90 if exctype:
90 if exctype:
91 self.ui.log('simplecache', 'cacher exiting due to error\n')
91 self.ui.log('simplecache', 'cacher exiting due to error\n')
92
92
93 def adjustcachekeystate(self, state):
93 def adjustcachekeystate(self, state):
94 # Needed in order to make tests deterministic. Don't copy this
94 # Needed in order to make tests deterministic. Don't copy this
95 # pattern for production caches!
95 # pattern for production caches!
96 del state[b'repo']
96 del state[b'repo']
97
97
98 def setcachekey(self, key):
98 def setcachekey(self, key):
99 self.key = key
99 self.key = key
100 return True
100 return True
101
101
102 def lookup(self):
102 def lookup(self):
103 if self.key not in CACHE:
103 if self.key not in CACHE:
104 self.ui.log('simplecache', 'cache miss for %s\n', self.key)
104 self.ui.log('simplecache', 'cache miss for %s\n', self.key)
105 return None
105 return None
106
106
107 entry = CACHE[self.key]
107 entry = CACHE[self.key]
108 self.ui.log('simplecache', 'cache hit for %s\n', self.key)
108 self.ui.log('simplecache', 'cache hit for %s\n', self.key)
109
109
110 redirectable = True
110 redirectable = True
111
111
112 if not self.cacheapi:
112 if not self.cacheapi:
113 redirectable = False
113 redirectable = False
114 elif not self.redirecttargets:
114 elif not self.redirecttargets:
115 redirectable = False
115 redirectable = False
116 else:
116 else:
117 clienttargets = set(self.redirecttargets)
117 clienttargets = set(self.redirecttargets)
118 ourtargets = set(t[b'name'] for t in loadredirecttargets(self.ui))
118 ourtargets = set(t[b'name'] for t in loadredirecttargets(self.ui))
119
119
120 # We only ever redirect to a single target (for now). So we don't
120 # We only ever redirect to a single target (for now). So we don't
121 # need to store which target matched.
121 # need to store which target matched.
122 if not clienttargets & ourtargets:
122 if not clienttargets & ourtargets:
123 redirectable = False
123 redirectable = False
124
124
125 if redirectable:
125 if redirectable:
126 paths = self.req.dispatchparts[:-3]
126 paths = self.req.dispatchparts[:-3]
127 paths.append(b'simplecache')
127 paths.append(b'simplecache')
128 paths.append(self.key)
128 paths.append(self.key)
129
129
130 url = b'%s/%s' % (self.req.advertisedbaseurl, b'/'.join(paths))
130 url = b'%s/%s' % (self.req.baseurl, b'/'.join(paths))
131
131
132 #url = b'http://example.com/%s' % self.key
132 #url = b'http://example.com/%s' % self.key
133 self.ui.log('simplecache', 'sending content redirect for %s to '
133 self.ui.log('simplecache', 'sending content redirect for %s to '
134 '%s\n', self.key, url)
134 '%s\n', self.key, url)
135 response = wireprototypes.alternatelocationresponse(
135 response = wireprototypes.alternatelocationresponse(
136 url=url,
136 url=url,
137 mediatype=b'application/mercurial-cbor')
137 mediatype=b'application/mercurial-cbor')
138
138
139 return {'objs': [response]}
139 return {'objs': [response]}
140
140
141 if self.cacheobjects:
141 if self.cacheobjects:
142 return {
142 return {
143 'objs': entry,
143 'objs': entry,
144 }
144 }
145 else:
145 else:
146 return {
146 return {
147 'objs': [wireprototypes.encodedresponse(entry)],
147 'objs': [wireprototypes.encodedresponse(entry)],
148 }
148 }
149
149
150 def onobject(self, obj):
150 def onobject(self, obj):
151 if self.cacheobjects:
151 if self.cacheobjects:
152 self.buffered.append(obj)
152 self.buffered.append(obj)
153 else:
153 else:
154 self.buffered.extend(self.encodefn(obj))
154 self.buffered.extend(self.encodefn(obj))
155
155
156 yield obj
156 yield obj
157
157
158 def onfinished(self):
158 def onfinished(self):
159 self.ui.log('simplecache', 'storing cache entry for %s\n', self.key)
159 self.ui.log('simplecache', 'storing cache entry for %s\n', self.key)
160 if self.cacheobjects:
160 if self.cacheobjects:
161 CACHE[self.key] = self.buffered
161 CACHE[self.key] = self.buffered
162 else:
162 else:
163 CACHE[self.key] = b''.join(self.buffered)
163 CACHE[self.key] = b''.join(self.buffered)
164
164
165 return []
165 return []
166
166
167 def makeresponsecacher(orig, repo, proto, command, args, objencoderfn,
167 def makeresponsecacher(orig, repo, proto, command, args, objencoderfn,
168 redirecttargets, redirecthashes):
168 redirecttargets, redirecthashes):
169 return memorycacher(repo.ui, command, objencoderfn, redirecttargets,
169 return memorycacher(repo.ui, command, objencoderfn, redirecttargets,
170 redirecthashes, proto._req)
170 redirecthashes, proto._req)
171
171
172 def loadredirecttargets(ui):
172 def loadredirecttargets(ui):
173 path = ui.config('simplecache', 'redirectsfile')
173 path = ui.config('simplecache', 'redirectsfile')
174 if not path:
174 if not path:
175 return []
175 return []
176
176
177 with open(path, 'rb') as fh:
177 with open(path, 'rb') as fh:
178 s = fh.read()
178 s = fh.read()
179
179
180 return stringutil.evalpythonliteral(s)
180 return stringutil.evalpythonliteral(s)
181
181
182 def getadvertisedredirecttargets(orig, repo, proto):
182 def getadvertisedredirecttargets(orig, repo, proto):
183 return loadredirecttargets(repo.ui)
183 return loadredirecttargets(repo.ui)
184
184
185 def extsetup(ui):
185 def extsetup(ui):
186 global CACHE
186 global CACHE
187
187
188 CACHE = util.lrucachedict(10000)
188 CACHE = util.lrucachedict(10000)
189
189
190 extensions.wrapfunction(wireprotov2server, 'makeresponsecacher',
190 extensions.wrapfunction(wireprotov2server, 'makeresponsecacher',
191 makeresponsecacher)
191 makeresponsecacher)
192 extensions.wrapfunction(wireprotov2server, 'getadvertisedredirecttargets',
192 extensions.wrapfunction(wireprotov2server, 'getadvertisedredirecttargets',
193 getadvertisedredirecttargets)
193 getadvertisedredirecttargets)
General Comments 0
You need to be logged in to leave comments. Login now