Skip to content

Commit 6541167

Browse files
author
Gordon B. McMillan
committed
Updates to use Richard's cool new indexer.
1 parent 678a3b8 commit 6541167

File tree

1 file changed

+77
-32
lines changed

1 file changed

+77
-32
lines changed

roundup/backends/back_metakit.py

Lines changed: 77 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ def __init__(self, config, journaltag=None):
2929
self._db = self.__open()
3030
self.indexer = Indexer(self.config.DATABASE)
3131
os.umask(0002)
32+
def post_init(self):
33+
if self.indexer.should_reindex():
34+
self.reindex()
35+
36+
def reindex(self):
37+
for klass in self.classes.values():
38+
for nodeid in klass.list():
39+
klass.index(nodeid)
40+
self.indexer.save_index()
41+
3242

3343
# --- defined in ping's spec
3444
def __getattr__(self, classname):
@@ -51,6 +61,7 @@ def commit(self):
5161
self._db.commit()
5262
for cl in self.classes.values():
5363
cl._commit()
64+
self.indexer.save_index()
5465
else:
5566
raise RuntimeError, "metakit is open RO"
5667
self.dirty = 0
@@ -68,7 +79,7 @@ def hasnode(self, classname, nodeid):
6879
def pack(self, pack_before):
6980
pass
7081
def addclass(self, cl):
71-
self.classes[cl.name] = cl
82+
self.classes[cl.classname] = cl
7283
def addjournal(self, tablenm, nodeid, action, params):
7384
tblid = self.tables.find(name=tablenm)
7485
if tblid == -1:
@@ -136,6 +147,8 @@ def __open(self):
136147
self.fastopen = 1
137148
else:
138149
self.__RW = 1
150+
if not self.fastopen:
151+
self.__RW = 1
139152
db = metakit.storage(db, self.__RW)
140153
hist = db.view('history')
141154
tables = db.view('tables')
@@ -182,7 +195,7 @@ class Class: # no, I'm not going to subclass the existing!
182195
privateprops = None
183196
def __init__(self, db, classname, **properties):
184197
self.db = weakref.proxy(db)
185-
self.name = classname
198+
self.classname = classname
186199
self.keyname = None
187200
self.ruprops = properties
188201
self.privateprops = { 'id' : hyperdb.String(),
@@ -245,7 +258,7 @@ def get(self, nodeid, propname, default=_marker, cache=1):
245258
if ndx is None:
246259
ndx = view.find(id=id)
247260
if ndx < 0:
248-
raise IndexError, "%s has no node %s" % (self.name, nodeid)
261+
raise IndexError, "%s has no node %s" % (self.classname, nodeid)
249262
self.idcache[id] = ndx
250263
raw = getattr(view[ndx], propname)
251264
rutyp = self.ruprops.get(propname, None)
@@ -273,10 +286,10 @@ def set(self, nodeid, **propvalues):
273286
id = int(nodeid)
274287
ndx = view.find(id=id)
275288
if ndx < 0:
276-
raise IndexError, "%s has no node %s" % (self.name, nodeid)
289+
raise IndexError, "%s has no node %s" % (self.classname, nodeid)
277290
row = view[ndx]
278291
if row._isdel:
279-
raise IndexError, "%s has no node %s" % (self.name, nodeid)
292+
raise IndexError, "%s has no node %s" % (self.classname, nodeid)
280293
oldnode = self.uncommitted.setdefault(id, {})
281294
changes = {}
282295

@@ -335,11 +348,11 @@ def set(self, nodeid, **propvalues):
335348
if prop.do_journal:
336349
# register the unlink with the old linked node
337350
if oldvalue:
338-
self.db.addjournal(link_class, value, _UNLINK, (self.name, str(row.id), key))
351+
self.db.addjournal(link_class, value, _UNLINK, (self.classname, str(row.id), key))
339352

340353
# register the link with the newly linked node
341354
if value:
342-
self.db.addjournal(link_class, value, _LINK, (self.name, str(row.id), key))
355+
self.db.addjournal(link_class, value, _LINK, (self.classname, str(row.id), key))
343356

344357
elif isinstance(prop, hyperdb.Multilink):
345358
if type(value) != _LISTTYPE:
@@ -369,7 +382,7 @@ def set(self, nodeid, **propvalues):
369382
rmvd.append(id)
370383
# register the unlink with the old linked node
371384
if prop.do_journal:
372-
self.db.addjournal(link_class, id, _UNLINK, (self.name, str(row.id), key))
385+
self.db.addjournal(link_class, id, _UNLINK, (self.classname, str(row.id), key))
373386

374387
# handle additions
375388
adds = []
@@ -381,7 +394,7 @@ def set(self, nodeid, **propvalues):
381394
adds.append(id)
382395
# register the link with the newly linked node
383396
if prop.do_journal:
384-
self.db.addjournal(link_class, id, _LINK, (self.name, str(row.id), key))
397+
self.db.addjournal(link_class, id, _LINK, (self.classname, str(row.id), key))
385398

386399
sv = getattr(row, key)
387400
i = 0
@@ -402,6 +415,8 @@ def set(self, nodeid, **propvalues):
402415
changes[key] = oldvalue
403416
if hasattr(prop, 'isfilename') and prop.isfilename:
404417
propvalues[key] = os.path.basename(value)
418+
if prop.indexme:
419+
self.db.indexer.add_text((self.classname, nodeid, key), value, 'text/plain')
405420

406421
elif isinstance(prop, hyperdb.Password):
407422
if not isinstance(value, password.Password):
@@ -437,11 +452,13 @@ def set(self, nodeid, **propvalues):
437452
if not row.creator:
438453
row.creator = self.db.curuserid
439454

455+
#XXX
456+
print "back_metakit.Class.set - dirty"
440457
self.db.dirty = 1
441458
if isnew:
442-
self.db.addjournal(self.name, nodeid, _CREATE, {})
459+
self.db.addjournal(self.classname, nodeid, _CREATE, {})
443460
else:
444-
self.db.addjournal(self.name, nodeid, _SET, changes)
461+
self.db.addjournal(self.classname, nodeid, _SET, changes)
445462

446463
def retire(self, nodeid):
447464
view = self.getview(1)
@@ -452,26 +469,26 @@ def retire(self, nodeid):
452469
oldvalues = self.uncommitted.setdefault(row.id, {})
453470
oldval = oldvalues['_isdel'] = row._isdel
454471
row._isdel = 1
455-
self.db.addjournal(self.name, nodeid, _RETIRE, {})
472+
self.db.addjournal(self.classname, nodeid, _RETIRE, {})
456473
iv = self.getindexview(1)
457474
ndx = iv.find(k=getattr(row, self.keyname),i=row.id)
458475
if ndx > -1:
459476
iv.delete(ndx)
460477
self.db.dirty = 1
461478
def history(self, nodeid):
462-
return self.db.gethistory(self.name, nodeid)
479+
return self.db.gethistory(self.classname, nodeid)
463480
def setkey(self, propname):
464481
if self.keyname:
465482
if propname == self.keyname:
466483
return
467-
raise ValueError, "%s already indexed on %s" % (self.name, self.keyname)
484+
raise ValueError, "%s already indexed on %s" % (self.classname, self.keyname)
468485
# first setkey for this run
469486
self.keyname = propname
470-
iv = self.db._db.view('_%s' % self.name)
487+
iv = self.db._db.view('_%s' % self.classname)
471488
if self.db.fastopen or iv.structure():
472489
return
473490
# very first setkey ever
474-
iv = self.db._db.getas('_%s[k:S,i:I]' % self.name)
491+
iv = self.db._db.getas('_%s[k:S,i:I]' % self.classname)
475492
iv = iv.ordered(1)
476493
#XXX
477494
print "setkey building index"
@@ -514,6 +531,8 @@ def find(self, **propspec):
514531

515532
vws = []
516533
for propname, ids in propspec:
534+
if type(ids) is _STRINGTYPE:
535+
ids = {ids:1}
517536
prop = self.ruprops[propname]
518537
view = self.getview()
519538
if isinstance(prop, hyperdb.Multilink):
@@ -551,7 +570,7 @@ def getprops(self, protected=1):
551570
def addprop(self, **properties):
552571
for key in properties.keys():
553572
if self.ruprops.has_key(key):
554-
raise ValueError, "%s is already a property of %s" % (key, self.name)
573+
raise ValueError, "%s is already a property of %s" % (key, self.classname)
555574
self.ruprops.update(properties)
556575
view = self.__getview()
557576
# ---- end of ping's spec
@@ -731,7 +750,17 @@ def stringFind(self, **requirements):
731750
return l
732751

733752
def addjournal(self, nodeid, action, params):
734-
self.db.addjournal(self.name, nodeid, action, params)
753+
self.db.addjournal(self.classname, nodeid, action, params)
754+
755+
def index(self, nodeid):
756+
''' Add (or refresh) the node to search indexes '''
757+
# find all the String properties that have indexme
758+
for prop, propclass in self.getprops().items():
759+
if isinstance(propclass, hyperdb.String) and propclass.indexme:
760+
# index them under (classname, nodeid, property)
761+
self.db.indexer.add_text((self.classname, nodeid, prop),
762+
str(self.get(nodeid, prop)))
763+
735764
# --- used by Database
736765
def _commit(self):
737766
""" called post commit of the DB.
@@ -762,24 +791,31 @@ def rollbackaction(self, action):
762791
# --- internal
763792
def __getview(self):
764793
db = self.db._db
765-
view = db.view(self.name)
794+
view = db.view(self.classname)
766795
if self.db.fastopen:
767796
return view.ordered(1)
768797
# is the definition the same?
798+
mkprops = view.structure()
769799
for nm, rutyp in self.ruprops.items():
770-
mkprop = getattr(view, nm, None)
800+
for mkprop in mkprops:
801+
if mkprop.name == nm:
802+
break
803+
else:
804+
mkprop = None
771805
if mkprop is None:
772-
#print "%s missing prop %s (%s)" % (self.name, nm, rutyp.__class__.__name__)
806+
#print "%s missing prop %s (%s)" % (self.classname, nm, rutyp.__class__.__name__)
773807
break
774808
if _typmap[rutyp.__class__] != mkprop.type:
775-
#print "%s - prop %s (%s) has wrong mktyp (%s)" % (self.name, nm, rutyp.__class__.__name__, mkprop.type)
809+
#print "%s - prop %s (%s) has wrong mktyp (%s)" % (self.classname, nm, rutyp.__class__.__name__, mkprop.type)
776810
break
777811
else:
778812
return view.ordered(1)
779813
# need to create or restructure the mk view
780814
# id comes first, so MK will order it for us
815+
#XXX
816+
print "back_metakit.Class.__getview - dirty!"
781817
self.db.dirty = 1
782-
s = ["%s[id:I" % self.name]
818+
s = ["%s[id:I" % self.classname]
783819
for nm, rutyp in self.ruprops.items():
784820
mktyp = _typmap[rutyp.__class__]
785821
s.append('%s:%s' % (nm, mktyp))
@@ -791,11 +827,11 @@ def __getview(self):
791827
def getview(self, RW=0):
792828
if RW and self.db.isReadOnly():
793829
self.db.getWriteAccess()
794-
return self.db._db.view(self.name).ordered(1)
830+
return self.db._db.view(self.classname).ordered(1)
795831
def getindexview(self, RW=0):
796832
if RW and self.db.isReadOnly():
797833
self.db.getWriteAccess()
798-
return self.db._db.view("_%s" % self.name).ordered(1)
834+
return self.db._db.view("_%s" % self.classname).ordered(1)
799835

800836
def _fetchML(sv):
801837
l = []
@@ -837,8 +873,11 @@ class FileName(hyperdb.String):
837873
}
838874
class FileClass(Class):
839875
' like Class but with a content property '
876+
default_mime_type = 'text/plain'
840877
def __init__(self, db, classname, **properties):
841878
properties['content'] = FileName()
879+
if not properties.has_key('type'):
880+
properties['type'] = hyperdb.String()
842881
Class.__init__(self, db, classname, **properties)
843882
def get(self, nodeid, propname, default=_marker, cache=1):
844883
x = Class.get(self, nodeid, propname, default, cache)
@@ -859,22 +898,28 @@ def create(self, **propvalues):
859898
if content.startswith('/tracker/download.php?'):
860899
self.set(newid, content='http://sourceforge.net'+content)
861900
return newid
862-
nm = bnm = '%s%s' % (self.name, newid)
901+
nm = bnm = '%s%s' % (self.classname, newid)
863902
sd = str(int(int(newid) / 1000))
864-
d = os.path.join(self.db.config.DATABASE, 'files', self.name, sd)
903+
d = os.path.join(self.db.config.DATABASE, 'files', self.classname, sd)
865904
if not os.path.exists(d):
866905
os.makedirs(d)
867906
nm = os.path.join(d, nm)
868907
open(nm, 'wb').write(content)
869908
self.set(newid, content = 'file:'+nm)
870-
self.db.indexer.add_files(d, bnm)
871-
self.db.indexer.save_index()
909+
mimetype = propvalues.get('type', self.default_mime_type)
910+
self.db.indexer.add_text((self.classname, newid, 'content'), content, mimetype)
872911
def undo(fnm=nm, action1=os.remove, indexer=self.db.indexer):
873912
remove(fnm)
874-
indexer.purge_entry(fnm, indexer.files, indexer.words)
875913
self.rollbackaction(undo)
876914
return newid
877-
915+
def index(self, nodeid):
916+
Class.index(self, nodeid)
917+
mimetype = self.get(nodeid, 'type')
918+
if not mimetype:
919+
mimetype = self.default_mime_type
920+
self.db.indexer.add_text((self.classname, nodeid, 'content'),
921+
self.get(nodeid, 'content'), mimetype)
922+
878923
# Yuck - c&p to avoid getting hyperdb.Class
879924
class IssueClass(Class):
880925

@@ -886,7 +931,7 @@ def __init__(self, db, classname, **properties):
886931
dictionary attempts to specify any of these properties or a
887932
"creation" or "activity" property, a ValueError is raised."""
888933
if not properties.has_key('title'):
889-
properties['title'] = hyperdb.String()
934+
properties['title'] = hyperdb.String(indexme='yes')
890935
if not properties.has_key('messages'):
891936
properties['messages'] = hyperdb.Multilink("msg")
892937
if not properties.has_key('files'):

0 commit comments

Comments
 (0)