@Override public List<ClientMetadata> getClients() { if (clients == null) { clients = new WatchedMap<>(zk, ZkPath.append(ringGroupPath, CLIENTS_PATH), new ElementLoader<WatchedThriftNode<ClientMetadata>>() { @Override public WatchedThriftNode<ClientMetadata> load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException, IOException { return new WatchedThriftNode<ClientMetadata>(zk, ZkPath.append(basePath, relPath), true, null, null, emptyClientMetadata); } }); } List<ClientMetadata> result = new ArrayList<ClientMetadata>(); for (WatchedThriftNode<ClientMetadata> client : clients.values()) { result.add(client.get()); } return result; }
@Override public T get(Object key) { ensureLoaded(); return internalMap.get(key); }
private void ensureLoaded() { // this lock is important so that when changes start happening, we // won't run into any concurrency issues boolean keysChanged = false; synchronized (notifyMutex) { // if the map is non-null, then it's already loaded and the watching // mechanism will take care of everything... if (!loaded) { // ...but if it's not loaded, we need to do the initial population. keysChanged = syncMap(); loaded = true; } } if (keysChanged) { fireListeners(); } }
@Test public void testIt() throws Exception { final ZooKeeperPlus zk = getZk(); final String colRoot = ZkPath.append(getRoot(), "collection"); zk.create(colRoot, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); final ElementLoader<String> elementLoader = (zk1, basePath, relPath) -> { try { return new String(zk1.getData(ZkPath.append(basePath, relPath), false, new Stat())); } catch (Exception e) { throw new RuntimeException(e); } }; final WatchedMap<String> c1 = new WatchedMap<>(zk, colRoot, elementLoader); dumpZk(); WaitUntil.orDie(() -> 0 == c1.size()); assertEquals(0, c1.size()); zk.create(ZkPath.append(colRoot, "first"), "data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); WaitUntil.orDie(() -> 1 == c1.size()); assertEquals(1, c1.size()); }
public ZkRingGroup(ZooKeeperPlus zk, String ringGroupPath, DomainGroup domainGroup, final Coordinator coordinator) throws InterruptedException, KeeperException { super(ZkPath.getFilename(ringGroupPath)); this.zk = zk; this.ringGroupPath = ringGroupPath; this.domainGroup = domainGroup; this.coordinator = coordinator; if (coordinator == null) { throw new IllegalArgumentException("Cannot initialize a ZkRingGroup with a null Coordinator."); } rings = new WatchedMap<ZkRing>(zk, ringGroupPath, new ElementLoader<ZkRing>() { @Override public ZkRing load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException { if (relPath.matches("ring-\\d+")) { return new ZkRing(zk, ZkPath.append(basePath, relPath), ZkRingGroup.this, coordinator, dataLocationChangeListener); } return null; } }); rings.addListener(new ZkRingGroup.RingsWatchedMapListener()); // Note: clients is lazy loaded in getClients() ringGroupConductorOnlinePath = ZkPath.append(ringGroupPath, RING_GROUP_CONDUCTOR_ONLINE_PATH); ringGroupConductorMode = new WatchedEnum<RingGroupConductorMode>(RingGroupConductorMode.class, zk, ringGroupConductorOnlinePath, false); }
domains = new WatchedMap<ZkDomain>(zk, domainsRoot, new WatchedMap.ElementLoader<ZkDomain>() { @Override public ZkDomain load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException { domainGroups = new WatchedMap<ZkDomainGroup>(zk, domainGroupsRoot, new WatchedMap.ElementLoader<ZkDomainGroup>() { @Override public ZkDomainGroup load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException { ringGroups = new WatchedMap<ZkRingGroup>(zk, ringGroupsRoot, new WatchedMap.ElementLoader<ZkRingGroup>() { @Override public ZkRingGroup load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException {
@Override public boolean removeHost(PartitionServerAddress address) throws IOException { for (Map.Entry<String, ZkHost> entry : hosts.entrySet()) { if (entry.getValue().getAddress().equals(address)) { ZkHost host = hosts.remove(entry.getKey()); host.delete(); fireDataLocationChangeListener(); return true; } } return false; }
@Override public boolean deleteDomainGroup(String domainGroupName) throws IOException { ZkDomainGroup domainGroup = domainGroups.remove(domainGroupName); if (domainGroup == null) { return false; } return domainGroup.delete(); }
@Override public DomainGroup addDomainGroup(String name) throws IOException { try { ZkDomainGroup dgc = ZkDomainGroup.create(zk, this, domainGroupsRoot, name); synchronized (domainGroups) { domainGroups.put(name, dgc); } return dgc; } catch (Exception e) { throw new IOException(e); } }
@Override public DomainGroup getDomainGroup(String domainGroupName) { return domainGroups.get(domainGroupName); }
@Override public Domain getDomainShallow(String domainName) { if (domains.isLoaded()) { return getDomain(domainName); } else { try { return new ZkDomain(zk, ZkPath.append(domainsRoot, domainName)); } catch (InterruptedException e) { return null; } catch (KeeperException e) { return null; } } }
detectCompletionConcurrently(zk, path, newChildrenRelPaths, awaiter, completionDetector);
}).start(); }; final WatchedMap<String> m = new WatchedMap<>(getZk(), getRoot(), elementLoader, completionDetector); assertEquals(0, m.size()); assertEquals(0, m.size()); WaitUntil.orDie(() -> 1 == m.size()); assertEquals(1, m.size());
public ZkRing(ZooKeeperPlus zk, final String ringPath, RingGroup ringGroup, final Coordinator coordinator, final DataLocationChangeListener dataLocationChangeListener) throws InterruptedException, KeeperException { super(parseRingNum(ringPath), ringGroup); this.zk = zk; this.ringPath = ringPath; this.coordinator = coordinator; this.dataLocationChangeListener = dataLocationChangeListener; if (coordinator == null) { throw new RuntimeException("Cannot initialize a ZkRing with a null Coordinator."); } hosts = new WatchedMap<ZkHost>(zk, ZkPath.append(ringPath, HOSTS_PATH_SEGMENT), new WatchedMap.ElementLoader<ZkHost>() { @Override public ZkHost load(ZooKeeperPlus zk, String basePath, String relPath) throws InterruptedException, KeeperException { return new ZkHost(zk, coordinator, ZkPath.append(basePath, relPath), dataLocationChangeListener, false, null, null); } }, new DotComplete()); hosts.addListener(new ZkRing.HostsWatchedMapListener()); }
public ZkDomain(ZooKeeperPlus zk, String path, boolean create, DomainMetadata initialMetadata) throws KeeperException, InterruptedException { this.zk = zk; this.path = path; this.name = ZkPath.getFilename(path); metadata = new WatchedThriftNode<DomainMetadata>(zk, path, true, create ? CreateMode.PERSISTENT : null, initialMetadata, new DomainMetadata()); if (create) { zk.ensureCreated(ZkPath.append(path, VERSIONS_PATH), null); } this.versions = new WatchedMap<ZkDomainVersion>(zk, ZkPath.append(path, VERSIONS_PATH), new WatchedMap.ElementLoader<ZkDomainVersion>() { @Override public ZkDomainVersion load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException { return new ZkDomainVersion(zk, ZkPath.append(basePath, relPath), getDomainVersionPropertiesSerialization()); } } ); }
@Override public boolean deleteRingGroup(String ringGroupName) throws IOException { ZkRingGroup ringGroup = ringGroups.remove(ringGroupName); if (ringGroup == null) { return false; } return ringGroup.delete(); } }
@Override public Domain addDomain(String domainName, int numParts, String storageEngineFactoryName, String storageEngineOptions, String partitionerName, List<String> requiredHostFlags) throws IOException { try { ZkDomain domain = ZkDomain.create(zk, domainsRoot, domainName, numParts, storageEngineFactoryName, storageEngineOptions, partitionerName, getNextDomainId(), requiredHostFlags); domains.put(domainName, domain); return domain; } catch (Exception e) { throw new IOException(e); } }
@Override public Domain getDomain(String domainName) { return domains.get(domainName); }
@Override public DomainVersion getVersionShallow(int versionNumber) throws IOException { if (versions.isLoaded()) { return findVersion(getVersions(), versionNumber); } else { try { return new ZkDomainVersion(zk, ZkPath.append(path, VERSIONS_PATH, ZkDomainVersion.getPathName(versionNumber)), getDomainVersionPropertiesSerialization()); } catch (InterruptedException e) { return null; } catch (KeeperException e) { return null; } } }
@Override public List<ConnectedServerMetadata> getLiveServers(){ if (servers == null) { // TODO this is a kinda temporary hack. ring groups in prod haven't created the servers path so we can't rely // on it being there. prolly sweep after migrating. try { zk.ensureCreated(ZkPath.append(ringGroupPath, SERVERS_PATH), null); } catch (Exception e) { LOG.error("Error creating server path!", e); } servers = new WatchedMap<WatchedThriftNode<ConnectedServerMetadata>>(zk, ZkPath.append(ringGroupPath, SERVER_NODE), new ElementLoader<WatchedThriftNode<ConnectedServerMetadata>>() { @Override public WatchedThriftNode<ConnectedServerMetadata> load(ZooKeeperPlus zk, String basePath, String relPath) throws KeeperException, InterruptedException, IOException { return new WatchedThriftNode<>(zk, ZkPath.append(basePath, relPath), true, null, null, emptyConnectedServerMetadata); } }); } ArrayList<ConnectedServerMetadata> result = Lists.newArrayList(); for (WatchedThriftNode<ConnectedServerMetadata> host : servers.values()) { result.add(host.get()); } return result; }