comparison bin/rdfdb @ 1045:c1face79c0e1

fix rdfdb's filename<->uri mapping system Ignore-this: 2236b295035273370138943857894699
author Drew Perttula <drewp@bigasterisk.com>
date Thu, 29 May 2014 06:46:18 +0000
parents a4632a7b2e17
children 473db8bebb8f
comparison
equal deleted inserted replaced
1044:a2081b9adfe4 1045:c1face79c0e1
117 from light9 import networking, showconfig, prof 117 from light9 import networking, showconfig, prof
118 from rdflib import ConjunctiveGraph, URIRef, Graph 118 from rdflib import ConjunctiveGraph, URIRef, Graph
119 from light9.rdfdb.graphfile import GraphFile 119 from light9.rdfdb.graphfile import GraphFile
120 from light9.rdfdb.patch import Patch, ALLSTMTS 120 from light9.rdfdb.patch import Patch, ALLSTMTS
121 from light9.rdfdb.rdflibpatch import patchQuads 121 from light9.rdfdb.rdflibpatch import patchQuads
122 122 from light9.rdfdb.file_vs_uri import correctToTopdirPrefix, fileForUri, uriFromFile
123 from light9.rdfdb.patchsender import sendPatch 123 from light9.rdfdb.patchsender import sendPatch
124 from light9.rdfdb.patchreceiver import makePatchEndpointPutMethod 124 from light9.rdfdb.patchreceiver import makePatchEndpointPutMethod
125 125
126 from twisted.internet.inotify import INotify 126 from twisted.internet.inotify import INotify
127 from run_local import log 127 from run_local import log
163 """ 163 """
164 find files, notice new files. 164 find files, notice new files.
165 165
166 This object watches directories. Each GraphFile watches its own file. 166 This object watches directories. Each GraphFile watches its own file.
167 """ 167 """
168 def __init__(self, topDirsToWatch, patch, getSubgraph): 168 def __init__(self, dirUriMap, patch, getSubgraph):
169 self.topDirsToWatch = topDirsToWatch 169 self.dirUriMap = dirUriMap # {abspath : uri prefix}
170 self.patch, self.getSubgraph = patch, getSubgraph 170 self.patch, self.getSubgraph = patch, getSubgraph
171 171
172 # files from cwd become uris starting with this. *should* be
173 # building uris from the show uri in $LIGHT9_SHOW/URI
174 # instead. Who wants to keep their data in the same dir tree
175 # as the source code?!
176 self.topUri = URIRef("http://light9.bigasterisk.com/")
177
178 self.graphFiles = {} # context uri : GraphFile 172 self.graphFiles = {} # context uri : GraphFile
179 173
180 self.notifier = INotify() 174 self.notifier = INotify()
181 self.notifier.startReading() 175 self.notifier.startReading()
182 176
183 self.findAndLoadFiles() 177 self.findAndLoadFiles()
184 178
185 def findAndLoadFiles(self): 179 def findAndLoadFiles(self):
186 self.initialLoad = True 180 self.initialLoad = True
187 try: 181 try:
188 for topdir in self.topDirsToWatch: 182 for topdir in self.dirUriMap:
189 for dirpath, dirnames, filenames in os.walk(topdir): 183 for dirpath, dirnames, filenames in os.walk(topdir):
190 for base in filenames: 184 for base in filenames:
191 self.watchFile(os.path.join(dirpath, base)) 185 self.watchFile(os.path.join(dirpath, base))
192 self.notifier.watch(FilePath(dirpath), autoAdd=True, 186 self.notifier.watch(FilePath(dirpath), autoAdd=True,
193 callbacks=[self.dirChange]) 187 callbacks=[self.dirChange])
207 FilePath) because we use its exact relative form in the 201 FilePath) because we use its exact relative form in the
208 context URI 202 context URI
209 """ 203 """
210 if not os.path.isfile(inFile): 204 if not os.path.isfile(inFile):
211 return 205 return
212 if not any(inFile.startswith(prefix) for prefix in self.topDirsToWatch): 206
213 for prefix in self.topDirsToWatch: 207 inFile = correctToTopdirPrefix(self.dirUriMap, inFile)
214 prefixAbs = os.path.abspath(prefix)
215 if inFile.startswith(prefixAbs):
216 inFile = prefix + inFile[len(prefixAbs):]
217 break
218 else:
219 raise ValueError("can't correct %s to start with one of %s" %
220 (inFile, self.topDirsToWatch))
221 if os.path.splitext(inFile)[1] not in ['.n3']: 208 if os.path.splitext(inFile)[1] not in ['.n3']:
222 return 209 return
223 210
224 # an n3 file with rules makes it all the way past this reading 211 # an n3 file with rules makes it all the way past this reading
225 # and the serialization. Then, on the receiving side, a 212 # and the serialization. Then, on the receiving side, a
233 # read into one file called config.n3. New versions won't read 220 # read into one file called config.n3. New versions won't read
234 # it. 221 # it.
235 if inFile.endswith("config.n3"): 222 if inFile.endswith("config.n3"):
236 return 223 return
237 224
238 ctx = self.uriFromFile(inFile) 225 ctx = uriFromFile(self.dirUriMap, inFile)
239 gf = GraphFile(self.notifier, inFile, ctx, 226 gf = GraphFile(self.notifier, inFile, ctx,
240 self.patch, self.getSubgraph) 227 self.patch, self.getSubgraph)
241 self.graphFiles[ctx] = gf 228 self.graphFiles[ctx] = gf
242 log.info("%s do initial read", inFile) 229 log.info("%s do initial read", inFile)
243 gf.reread() 230 gf.reread()
254 graph is still a reasonable thing to do, though. 241 graph is still a reasonable thing to do, though.
255 """ 242 """
256 g = self.getSubgraph(ctx) 243 g = self.getSubgraph(ctx)
257 244
258 if ctx not in self.graphFiles: 245 if ctx not in self.graphFiles:
259 outFile = self.fileForUri(ctx) 246 outFile = fileForUri(self.dirUriMap, ctx)
260 log.info("starting new file %r", outFile) 247 log.info("starting new file %r", outFile)
261 self.graphFiles[ctx] = GraphFile(self.notifier, outFile, ctx, 248 self.graphFiles[ctx] = GraphFile(self.notifier, outFile, ctx,
262 self.patch, self.getSubgraph) 249 self.patch, self.getSubgraph)
263 250
264 def dirtyFiles(self, ctxs): 251 def dirtyFiles(self, ctxs):
272 """ 259 """
273 for ctx in ctxs: 260 for ctx in ctxs:
274 g = self.getSubgraph(ctx) 261 g = self.getSubgraph(ctx)
275 self.graphFiles[ctx].dirty(g) 262 self.graphFiles[ctx].dirty(g)
276 263
277 def uriFromFile(self, filename):
278 assert filename.endswith('.n3'), filename
279 if not any(filename.startswith(t) for t in self.topDirsToWatch):
280 raise ValueError("filename %s doesn't start with any of %s" %
281 (filename, self.topDirsToWatch))
282 return URIRef(self.topUri + filename[:-len('.n3')])
283
284 def fileForUri(self, ctx):
285 assert isinstance(ctx, URIRef), ctx
286 if not ctx.startswith(self.topUri):
287 raise ValueError("don't know what filename to use for %s" % ctx)
288 return ctx[len(self.topUri):] + ".n3"
289
290 264
291 class Db(object): 265 class Db(object):
292 """ 266 """
293 the master graph, all the connected clients, all the files we're watching 267 the master graph, all the connected clients, all the files we're watching
294 """ 268 """
295 def __init__(self, topDirsToWatch): 269 def __init__(self, dirUriMap):
296 270
297 self.clients = [] 271 self.clients = []
298 self.graph = ConjunctiveGraph() 272 self.graph = ConjunctiveGraph()
299 273
300 self.watchedFiles = WatchedFiles(topDirsToWatch, 274 self.watchedFiles = WatchedFiles(dirUriMap,
301 self.patch, self.getSubgraph) 275 self.patch, self.getSubgraph)
302 276
303 self.summarizeToLog() 277 self.summarizeToLog()
304 278
305 def patch(self, p, dueToFileChange=False): 279 def patch(self, p, dueToFileChange=False):
442 help="logging.DEBUG") 416 help="logging.DEBUG")
443 (options, args) = parser.parse_args() 417 (options, args) = parser.parse_args()
444 418
445 log.setLevel(logging.DEBUG if options.verbose else logging.INFO) 419 log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
446 420
447 db = Db(topDirsToWatch=[os.environ['LIGHT9_SHOW']]) 421 db = Db(dirUriMap={os.environ['LIGHT9_SHOW'].rstrip('/') + '/':
422 URIRef('http://light9.bigasterisk.com/show/dance2014/')})
448 423
449 from twisted.python import log as twlog 424 from twisted.python import log as twlog
450 twlog.startLogging(sys.stdout) 425 twlog.startLogging(sys.stdout)
451 426
452 port = 8051 427 port = 8051