package divconq.hub; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import divconq.bus.Message; import divconq.db.DataRequest; import divconq.db.ObjectResult; import divconq.db.rocks.DatabaseManager; import divconq.filestore.CommonPath; import divconq.io.FileStoreEvent; import divconq.lang.op.FuncCallback; import divconq.lang.op.OperationCallback; import divconq.log.Logger; import divconq.struct.CompositeStruct; import divconq.struct.ListStruct; import divconq.struct.RecordStruct; import divconq.struct.Struct; import divconq.util.StringUtil; public class DomainsManager { // domain tracking protected DomainNameMapping<DomainInfo> dnamemap = new DomainNameMapping<>(); protected ConcurrentHashMap<String, DomainInfo> dsitemap = new ConcurrentHashMap<>(); public Collection<DomainInfo> getDomains() { return this.dsitemap.values(); } public void dumpDomainNames() { // TODO this.dnamemap.dumpDomainNames(); } public String resolveDomainId(String domain) { if (StringUtil.isEmpty(domain)) return null; // if this is a domain id then return it if (this.dsitemap.containsKey(domain)) return domain; // if not an id then try lookup of domain name DomainInfo di = this.dnamemap.get(domain); if (di != null) return di.getId(); return null; } public DomainInfo resolveDomainInfo(String domain) { if (StringUtil.isEmpty(domain)) return null; // if this is a domain id then return it DomainInfo di = this.dsitemap.get(domain); if (di != null) return di; // if not an id then try lookup of domain name di = this.dnamemap.get(domain); if (di != null) return di; return null; } public DomainInfo getDomainInfo(String id) { if (StringUtil.isEmpty(id)) return null; return this.dsitemap.get(id); } public void updateDomainRecord(String did, RecordStruct drec) { DomainInfo di = DomainsManager.this.dsitemap.get(did); // update old if (di != null) { ListStruct names = di.getNames(); if (names != null) for (Struct dn : names.getItems()) { String n = Struct.objectToCharsStrict(dn).toString(); DomainsManager.this.dnamemap.remove(n); } di.load(drec); } // insert new else { di = new DomainInfo(); di.load(drec); DomainsManager.this.dsitemap.put(did, di); } ListStruct names = di.getNames(); if (names != null) for (Struct dn : names.getItems()) { String n = Struct.objectToCharsStrict(dn).toString(); DomainsManager.this.dnamemap.add(n, di); } } public void init() { HubDependency domdep = new HubDependency("Domains"); domdep.setPassRun(false); Hub.instance.addDependency(domdep); Hub.instance.subscribeToEvent(HubEvents.DomainAdded, new IEventSubscriber() { @Override public void eventFired(Object e) { String did = (String) e; Hub.instance.getBus().sendMessage( (Message) new Message("dcDomains", "Manager", "Load") .withField("Body", new RecordStruct().withField("Id", did)), result -> { // if this fails the hub cannot start if (result.hasErrors()) { Logger.error("Unable to load new domain into hub"); return; } DomainsManager.this.updateDomainRecord(did, result.getBodyAsRec()); } ); } }); Hub.instance.subscribeToEvent(HubEvents.DomainUpdated, new IEventSubscriber() { @Override public void eventFired(Object e) { String did = (String) e; Hub.instance.getBus().sendMessage( (Message) new Message("dcDomains", "Manager", "Load") .withField("Body", new RecordStruct().withField("Id", did)), result -> { // if this fails the hub cannot start if (result.hasErrors()) { Logger.error("Unable to update domain in hub"); return; } DomainsManager.this.updateDomainRecord(did, result.getBodyAsRec()); } ); } }); // register for file store events before we start any services that might listen to these events // we need to catch domain config change events if (Hub.instance.getPublicFileStore() != null) { /* Examples: ./dcw/[domain alias]/config holds web setting for domain - settings.xml are the general settings (dcmHomePage - dcmDefaultTemplate[path]) - editable in CMS only - dictionary.xml is the domain level dictionary - direct edit by web dev - vars.json is the domain level variable store - direct edit by web dev */ FuncCallback<FileStoreEvent> localfilestorecallback = new FuncCallback<FileStoreEvent>() { @Override public void callback() { this.resetCalledFlag(); CommonPath p = this.getResult().getPath(); //System.out.println(p); // only notify on config updates if (p.getNameCount() < 4) return; // must be inside a domain or we don't care String mod = p.getName(0); String domain = p.getName(1); String section = p.getName(2); if ("dcw".equals(mod)) { for (DomainInfo wdomain : DomainsManager.this.dsitemap.values()) { if (domain.equals(wdomain.getAlias())) { if (("config".equals(section) || "services".equals(section) || "glib".equals(section) || "buckets".equals(section))) { wdomain.reloadSettings(); Hub.instance.fireEvent(HubEvents.DomainConfigChanged, wdomain); } wdomain.fileChanged(this.getResult()); break; } } } } }; Hub.instance.getPublicFileStore().register(localfilestorecallback); } Hub.instance.getBus().sendMessage( new Message("dcDomains", "Manager", "LoadAll"), result -> { // if this fails the hub cannot start if (result.hasErrors()) { // stop if we think we are connected, but if not then wait maybe we'll connect again and trigger this load again if (Hub.instance.state == HubState.Connected) Hub.instance.stop(); return; } ListStruct domains = result.getBodyAsList(); for (Struct d : domains.getItems()) { RecordStruct drec = (RecordStruct) d; String did = drec.getFieldAsString("Id"); DomainsManager.this.updateDomainRecord(did, drec); } Hub.instance.removeDependency(domdep.source); } ); } public void initFromDB(DatabaseManager db, OperationCallback callback) { DataRequest req = new DataRequest("dcLoadDomains").withRootDomain(); // use root for this request db.submit(req, new ObjectResult() { @Override public void process(CompositeStruct result) { // if this fails the hub cannot start if (this.hasErrors()) { callback.complete(); return; } ListStruct domains = (ListStruct) result; for (Struct d : domains.getItems()) { RecordStruct drec = (RecordStruct) d; String did = drec.getFieldAsString("Id"); DomainsManager.this.updateDomainRecord(did, drec); } callback.complete(); } }); } }