sclass TripleIndex extends VirtualNodeIndex { SyncListMultiMap index = caseInsensitiveSyncListMultiMap(); Map websByID = synchroHashMap(); bool activated; // are we the main index (see tripleIndex()) int numWebs() { ret l(websByID); } L get(S query) { ret ai_triplesToWebNodes_lazyList(index.get(query)); } Web getWeb(GlobalID id) { ret webFromTriple(websByID.get(id)); } void addWeb(Web web) { if (web == null) ret; TripleWeb w = ai_webToTripleWeb(web); if (w == null) fail("Skipping non-tripelizable web: " + webToStringShort(web)); synchronized(index) { for (S s : lithashset(w.a, w.b, w.c)) { // only once index.put(s, w); } } websByID.put(w.globalID(), w); } void removeWeb(Web web) { if (web == null) ret; TripleWeb w = ai_webToTripleWeb(web); if (w == null) ret; GlobalID id = w.globalID(); websByID.remove(id); indexRemove(w.a, id); indexRemove(w.b, id); indexRemove(w.c, id); } // internal void indexRemove(S term, GlobalID globalID) { L l = index.get(term); for i over l: if (eq(l.get(i).globalID(), globalID)) { index.remove(term, l.get(i)); ret; } } void clear() { index.clear(); websByID.clear(); } void activate { if (!activated) { activated = true; ai_onNewOrRemovedWeb(func(Web web) { addWeb(web); false; }, func(Web web) { removeWeb(web); false; }); } } }