/** * update the quota for the given path * * @param path * the path to be used */ private void updateQuotaForPath(String path) { Counts c = new Counts(); getCounts(path, c); StatsTrack strack = new StatsTrack(); strack.setBytes(c.bytes); strack.setCount(c.count); String statPath = Quotas.quotaZookeeper + path + "/" + Quotas.statNode; DataNode node = getNode(statPath); // it should exist if (node == null) { LOG.warn("Missing quota stat node " + statPath); return; } synchronized (node) { node.data = strack.toString().getBytes(); } }
@Override public boolean exec() throws KeeperException, InterruptedException { String path = args[1]; String absolutePath = Quotas.quotaZookeeper + path + "/" + Quotas.limitNode; try { err.println("absolute path is " + absolutePath); Stat stat = new Stat(); byte[] data = zk.getData(absolutePath, false, stat); StatsTrack st = new StatsTrack(new String(data)); out.println("Output quota for " + path + " " + st.toString()); data = zk.getData(Quotas.quotaZookeeper + path + "/" + Quotas.statNode, false, stat); out.println("Output stat for " + path + " " + new StatsTrack(new String(data)).toString()); } catch (KeeperException.NoNodeException ne) { err.println("quota for " + path + " does not exist."); } return false; }
/** * this method traverses the quota path and update the path trie and sets * * @param path */ private void traverseNode(String path) { DataNode node = getNode(path); String children[] = null; synchronized (node) { Set<String> childs = node.getChildren(); if (childs != null) { children = childs.toArray(new String[childs.size()]); } } if (children == null || children.length == 0) { // this node does not have a child // is the leaf node // check if its the leaf node String endString = "/" + Quotas.limitNode; if (path.endsWith(endString)) { // ok this is the limit node // get the real node and update // the count and the bytes String realPath = path.substring(Quotas.quotaZookeeper .length(), path.indexOf(endString)); updateQuotaForPath(realPath); this.pTrie.addPath(realPath); } return; } for (String child : children) { traverseNode(path + "/" + child); } }
/** * this method sets up the path trie and sets up stats for quota nodes */ private void setupQuota() { String quotaPath = Quotas.quotaZookeeper; DataNode node = getNode(quotaPath); if (node == null) { return; } traverseNode(quotaPath); }
@Test(timeout = 60000) public void testPathTrieClearOnDeserialize() throws Exception { //Create a DataTree with quota nodes so PathTrie get updated DataTree dserTree = new DataTree(); dserTree.createNode("/bug", new byte[20], null, -1, 1, 1, 1); dserTree.createNode(Quotas.quotaZookeeper+"/bug", null, null, -1, 1, 1, 1); dserTree.createNode(Quotas.quotaPath("/bug"), new byte[20], null, -1, 1, 1, 1); dserTree.createNode(Quotas.statPath("/bug"), new byte[20], null, -1, 1, 1, 1); //deserialize a DataTree; this should clear the old /bug nodes and pathTrie DataTree tree = new DataTree(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); BinaryOutputArchive oa = BinaryOutputArchive.getArchive(baos); tree.serialize(oa, "test"); baos.flush(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); BinaryInputArchive ia = BinaryInputArchive.getArchive(bais); dserTree.deserialize(ia, "test"); Field pfield = DataTree.class.getDeclaredField("pTrie"); pfield.setAccessible(true); PathTrie pTrie = (PathTrie)pfield.get(dserTree); //Check that the node path is removed from pTrie Assert.assertEquals("/bug is still in pTrie", "", pTrie.findMaxPrefix("/bug")); }
/** * this method traverses the quota path and update the path trie and sets * * @param path */ private void traverseNode(String path) { DataNode node = getNode(path); String children[] = null; synchronized (node) { Set<String> childs = node.getChildren(); children = childs.toArray(new String[childs.size()]); } if (children.length == 0) { // this node does not have a child // is the leaf node // check if its the leaf node String endString = "/" + Quotas.limitNode; if (path.endsWith(endString)) { // ok this is the limit node // get the real node and update // the count and the bytes String realPath = path.substring(Quotas.quotaZookeeper .length(), path.indexOf(endString)); updateQuotaForPath(realPath); this.pTrie.addPath(realPath); } return; } for (String child : children) { traverseNode(path + "/" + child); } }
/** * this method deletes quota for a node. * * @param zk the zookeeper client * @param path the path to delete quota for * @param bytes true if number of bytes needs to be unset * @param numNodes true if number of nodes needs to be unset * @return true if quota deletion is successful * @throws KeeperException * @throws IOException * @throws InterruptedException */ public static boolean delQuota(ZooKeeper zk, String path, boolean bytes, boolean numNodes) throws KeeperException, IOException, InterruptedException, MalformedPathException { String parentPath = Quotas.quotaZookeeper + path; String quotaPath = Quotas.quotaZookeeper + path + "/" + Quotas.limitNode; if (zk.exists(quotaPath, false) == null) { System.out.println("Quota does not exist for " + path); return true; } byte[] data = null; try { data = zk.getData(quotaPath, false, new Stat()); } catch (IllegalArgumentException ex) { throw new MalformedPathException(ex.getMessage()); } catch (KeeperException.NoNodeException ne) { System.err.println("quota does not exist for " + path); return true; } StatsTrack strack = new StatsTrack(new String(data)); if (bytes && !numNodes) { strack.setBytes(-1L); zk.setData(quotaPath, strack.toString().getBytes(), -1); } else if (!bytes && numNodes) { strack.setCount(-1); zk.setData(quotaPath, strack.toString().getBytes(), -1); } else if (bytes && numNodes) { // delete till you can find a node with more than // one child List<String> children = zk.getChildren(parentPath, false); /// delete the direct children first for (String child : children) { zk.delete(parentPath + "/" + child, -1); } // cut the tree till their is more than one child trimProcQuotas(zk, parentPath); } return true; }
/** * trim the quota tree to recover unwanted tree elements in the quota's tree * * @param zk the zookeeper client * @param path the path to start from and go up and see if their is any * unwanted parent in the path. * @return true if sucessful * @throws KeeperException * @throws IOException * @throws InterruptedException */ private static boolean trimProcQuotas(ZooKeeper zk, String path) throws KeeperException, IOException, InterruptedException { if (Quotas.quotaZookeeper.equals(path)) { return true; } List<String> children = zk.getChildren(path, false); if (children.size() == 0) { zk.delete(path, -1); String parent = path.substring(0, path.lastIndexOf('/')); return trimProcQuotas(zk, parent); } else { return true; } }
private static void checkIfParentQuota(ZooKeeper zk, String path) throws InterruptedException, KeeperException { final String[] splits = path.split("/"); String quotaPath = Quotas.quotaZookeeper; for (String str : splits) { if (str.length() == 0) { // this should only be for the beginning of the path // i.e. "/..." - split(path)[0] is empty string before first '/' continue; } quotaPath += "/" + str; List<String> children = null; try { children = zk.getChildren(quotaPath, false); } catch (KeeperException.NoNodeException ne) { // LOG.debug("child removed during quota check", ne); return; } if (children.size() == 0) { return; } for (String child : children) { if (Quotas.limitNode.equals(child)) { throw new IllegalArgumentException(path + " has a parent " + quotaPath + " which has a quota"); } } } }
/** * trim the quota tree to recover unwanted tree elements in the quota's tree * * @param zk * the zookeeper client * @param path * the path to start from and go up and see if their is any * unwanted parent in the path. * @return true if sucessful * @throws KeeperException * @throws IOException * @throws InterruptedException */ public static boolean trimProcQuotas(ZooKeeper zk, String path) throws KeeperException, IOException, InterruptedException { if (Quotas.quotaZookeeper.equals(path)) { return true; } List<String> children = zk.getChildren(path, false); if (children.size() == 0) { zk.delete(path, -1); String parent = path.substring(0, path.lastIndexOf('/')); return trimProcQuotas(zk, parent); } else { return true; } }