/** * @throws KeeperException * @throws InterruptedException * @throws NoSuchElementException */ protected byte[] getNext(boolean waitForElement, boolean deleteElement) throws KeeperException, InterruptedException, NoSuchElementException { TreeMap<KEY, String> orderedChildren; // element, take, and remove follow the same pattern. // We want to return the child node with the smallest sequence number. // Since other clients are remove()ing and take()ing nodes concurrently, // the child with the smallest sequence number in orderedChildren might // be gone by the time we check. // We don't call getChildren again until we have tried the rest of the // nodes in sequence order, // BUT if the children change with a higher priority // than the current child we are getting, then we reload all the // children. while (true) { PriorityLatchChildWatcher childWatcher = new PriorityLatchChildWatcher(); try { orderedChildren = orderedChildren(childWatcher); } catch (KeeperException.NoNodeException e) { if (waitForElement) { zookeeper.create(dir, new byte[0], acl, CreateMode.PERSISTENT); continue; } else { throw new NoSuchElementException(); } } if (orderedChildren.size() == 0) { if (waitForElement) { childWatcher.awaitChange(); continue; } else { throw new NoSuchElementException(); } } for (String headNode : orderedChildren.values()) { String path = dir + "/" + headNode; try { byte[] data = zookeeper.getData(path, false, null); if (childWatcher.hasChangedHigherThan(keyHandler.getPriority(headNode))) { break; } if (deleteElement) { zookeeper.delete(path, -1); } return data; } catch (KeeperException.NoNodeException e) { // Another client deleted the node first. } } } // while loop end }
/** * Returns a Map of the children, ordered by id. * * @param watcher optional watcher on getChildren() operation. * @return map from id to child name for all children */ private TreeMap<KEY, String> orderedChildren(Watcher watcher) throws KeeperException, InterruptedException { TreeMap<KEY, String> orderedChildren = new TreeMap<KEY, String>(); List<String> childNames = null; try { childNames = zookeeper.getChildren(dir, watcher); } catch (KeeperException.NoNodeException e) { throw e; } for (String childName : childNames) { try { /* * CHANGED FROM... if(!childName.regionMatches(0, prefix, 0, * prefix.length())){ * LOGGER.warn("Found child node with improper name: " + * childName); continue; } String suffix = * childName.substring(prefix.length()); Long childId = new * Long(suffix); */ // Check format if (!keyHandler.hasValidName(childName)) { LOGGER.warn("Found child node with improper name: " + childName); continue; } KEY childId = keyHandler.generateKey(childName); orderedChildren.put(childId, childName); } catch (NumberFormatException e) { LOGGER.warn("Found child node with improper format : " + childName + " " + e, e); } } return orderedChildren; }
/** * Inserts data into queue. * * @param data * @return true if data was successfully added */ public boolean offer(byte[] data, PRIORITY priority) throws KeeperException, InterruptedException { while (true) { try { // WAS: // zookeeper.create(dir+"/"+prefix, data, acl, // CreateMode.PERSISTENT_SEQUENTIAL); zookeeper.create( dir + "/" + keyHandler.generateChildNamePrefix(priority), data, acl, CreateMode.PERSISTENT_SEQUENTIAL); return true; } catch (KeeperException.NoNodeException e) { zookeeper.create(dir, new byte[0], acl, CreateMode.PERSISTENT); } } }