Untitled
unknown
java
2 years ago
16 kB
3
Indexable
import java.util.*; import java.util.concurrent.*; class TreeNode { public String value; private ArrayList<TreeNode> children; private boolean lock; public int parentLockCount; public int childLockCount; private TreeNode parentNode; private int userId; public TreeNode (String value, TreeNode parentNode) { this.value = value; this.parentNode = parentNode; // defaults this.lock = false; this.parentLockCount = 0; this.childLockCount = 0; this.children = new ArrayList<>(); this.userId = -1; } public void addChild(TreeNode child) { this.children.add(child); } public synchronized boolean isLocked() { return this.lock; } public TreeNode getParent() { return this.parentNode; } public synchronized void lockNode(int userId) { this.lock = true; this.userId = userId; } public synchronized void unlockNode() { this.lock = false; this.userId = -1; } public synchronized int getLocker() { return this.userId; } public synchronized void changeParentCount(int count) { this.parentLockCount += count; } public synchronized void changeChildCount(int count) { this.childLockCount += count; } @Override public String toString() { return "TreeNode{" + "value='" + value + '\'' + ", lock=" + lock + ", parentLockCount=" + parentLockCount + ", childLockCount=" + childLockCount + ", parentNode=" + (parentNode == null ? "NULL" : parentNode.value) + ", userId=" + userId + '}'; } public ArrayList<TreeNode> getChildren() { return this.children; } } public class Main { private HashMap<String, TreeNode> store = new HashMap<>(); private synchronized TreeNode generateTree (ArrayList<String> strings, int m) { TreeNode root = new TreeNode(strings.get(0), null); store.put(strings.get(0), root); Queue<TreeNode> queue = new ArrayDeque<>(); queue.add(root); int idx = 1; while(!queue.isEmpty()) { TreeNode current = queue.poll(); if (idx >= strings.size()) continue; // children for (int i = idx; i < idx + m; i++) { TreeNode currChild = new TreeNode(strings.get(i), current); store.put(strings.get(i), currChild); queue.add(currChild); current.addChild(currChild); } idx+=m; } return root; } private void printTree(TreeNode root) { if (root == null) return; System.out.println(root); ArrayList<TreeNode> children = root.getChildren(); for (TreeNode child : children) { printTree(child); } } // utility private void propoagateToChild (TreeNode current, int value) { synchronized (this) { Queue<TreeNode> queue = new ArrayDeque<>(); queue.add(current); while (!queue.isEmpty()) { TreeNode curr = queue.poll(); if (current != curr) curr.changeParentCount(value); ArrayList<TreeNode> children = curr.getChildren(); queue.addAll(children); } } } private boolean checkChildLocks (TreeNode current, int userId, ArrayList<TreeNode> lockedNodes) { Queue<TreeNode> queue = new ArrayDeque<>(); queue.add(current); while(!queue.isEmpty()) { TreeNode curr = queue.poll(); ArrayList<TreeNode> children = curr.getChildren(); for (TreeNode child : children) { if (child.isLocked()) { if (child.getLocker() == userId) { lockedNodes.add(child); } else { return false; } } queue.add(child); } } return true; } public synchronized boolean lock (String value, int userId) { if (!store.containsKey(value)) return false; TreeNode current = store.get(value); // check node and parents if (current.parentLockCount != 0) return false; // check children if (current.childLockCount != 0) return false; // lock the node current.lockNode(userId); // propagate the lock to parent and child nodes TreeNode prntNode = current.getParent(); while(prntNode != null) { // prntNode.childLockCount++; prntNode.changeChildCount(+1); prntNode = prntNode.getParent(); } propoagateToChild(current, 1); return true; } public synchronized String verboseLock(String value, int userId) { System.out.println("lock>>" + Thread.currentThread().getName() + " [Value : " + value + " userid : " + userId + "]"); if (!store.containsKey(value)) return "[LOCK]Node > " + value + " status > FAILED"; TreeNode current = store.get(value); // check node and parents if (current.parentLockCount != 0) return "[LOCK]Node > " + value + " status > FAILED"; // check children if (current.childLockCount != 0) return "[LOCK]Node > " + value + " status > FAILED"; // lock the node current.lockNode(userId); // propagate the lock to parent and child nodes TreeNode prntNode = current.getParent(); while(prntNode != null) { // prntNode.childLockCount++; prntNode.changeChildCount(+1); prntNode = prntNode.getParent(); } propoagateToChild(current, 1); return "[LOCK]Node > " + value + " status > PASS"; } public synchronized boolean unlock(String value, int userId) { if (!store.containsKey(value)) return false; TreeNode current = store.get(value); if (!current.isLocked()) return false; if (current.isLocked() && current.getLocker() != userId) return false; // lock the node current.unlockNode(); // propagate the unlock to parent and child TreeNode prntNode = current.getParent(); while(prntNode != null) { // prntNode.childLockCount--; prntNode.changeChildCount(-1); prntNode = prntNode.getParent(); } propoagateToChild(current, -1); return true; } public synchronized String verboseUnlock (String value, int userId) { // System.out.println("[Value : " + value + " userid : " + userId + "]"); System.out.println("Unlock>>" + Thread.currentThread().getName() + " [Value : " + value + " userid : " + userId + "]"); if (!store.containsKey(value)) return "[UNLOCK]Node > " + value + " status > FAILED"; TreeNode current = store.get(value); if (!current.isLocked()) return "[UNLOCK]Node > " + value + " status > FAILED"; if (current.isLocked() && current.getLocker() != userId) return "[UNLOCK]Node > " + value + " status > FAILED"; // lock the node current.unlockNode(); // propagate the unlock to parent and child TreeNode prntNode = current.getParent(); while(prntNode != null) { // prntNode.childLockCount--; prntNode.changeChildCount(-1); prntNode = prntNode.getParent(); } propoagateToChild(current, -1); return "[UNLOCK]Node > " + current.value + " status > PASS"; } public synchronized boolean upgrade(String value, int userId) { if (!store.containsKey(value)) return false; TreeNode current = store.get(value); if (current.isLocked()) return false; // check if any ancestor is locked if (current.parentLockCount != 0) return false; // check child nodes if (current.childLockCount != 0) { ArrayList<TreeNode> lockedChildNodes = new ArrayList<>(); boolean childLocksValid = checkChildLocks(current, userId, lockedChildNodes); if (childLocksValid) { // unlock all the child nodes for (TreeNode childNodes : lockedChildNodes) { unlock(childNodes.value, userId); } } else { return false; // all child nodes are not of the same lock } } else { return false; // no locked child nodes are there } lock(value, userId); return true; // child nodes unlocked. } public synchronized String verboseUpgrade(String value, int userId) { // System.out.println("[Value : " + value + " userid : " + userId + "]"); System.out.println("upgrade>>" + Thread.currentThread().getName() + " [Value : " + value + " userid : " + userId + "]"); if (!store.containsKey(value)) return "[UPGRADE]Node > " + value + " status > FAILED"; TreeNode current = store.get(value); if (current.isLocked()) return "[UPGRADE]Node > " + value + " status > FAILED"; // check if any ancestor is locked if (current.parentLockCount != 0) return "[UPGRADE]Node > " + value + " status > FAILED"; // check child nodes if (current.childLockCount != 0) { ArrayList<TreeNode> lockedChildNodes = new ArrayList<>(); boolean childLocksValid = checkChildLocks(current, userId, lockedChildNodes); if (childLocksValid) { // unlock all the child nodes for (TreeNode childNodes : lockedChildNodes) { unlock(childNodes.value, userId); } } else { return "[UPGRADE]Node > " + value + " status > FAILED"; // all child nodes are not of the same lock } } else { return "[UPGRADE]Node > " + value + " status > FAILED"; // no locked child nodes are there } lock(value, userId); return "[UPGRADE]Node > " + value + " status > PASS"; // child nodes unlocked. } public static void main(String[] args) { int n = 7, m = 2, q = 4; String[] arr = new String[] { "World", "Asia", "Africa", "India", "China", "SouthAfrica", "Egypt" }; ArrayList<String> arrLst = new ArrayList<>(); Collections.addAll(arrLst, arr); /* "World", 0 / \ "Asia", 1 "Africa", 2 / \ / \ "India", 3 "China", 4 "SouthAfrica",5 "Egypt", 6 */ Main object = new Main(); System.out.println(arrLst + " : " + arrLst.size()); TreeNode root = object.generateTree(arrLst, m); //out.println("Tree generated : "); //object.printTree(root); // QUERIES String[] queries = new String[] { "1 China 9", "2 India 9", "3 Asia 9", "2 India 9" }; String[] queries2 = new String[] { "1 Asia 122", "1 SouthAfrica 122", "3 World 122", "2 Asia 122", "1 SouthAfrica 123", "1 India 126", "2 World 122", "1 China 122", "1 Egypt 122", "3 Africa 122" }; q = queries2.length; // DEBUG // System.out.println(object.lock("Asia", 122)); // System.out.println(object.lock("SouthAfrica", 122)); // System.out.println(object.upgrade("World", 122)); // Create threads // # of threads = # of queries // ExecutorService executors = Executors.newFixedThreadPool(q); // List<Callable<Boolean>> callableTasks = new ArrayList<>(); // stores the tasks. long startTime = System.currentTimeMillis(); // Testing .. ExecutorService executors = Executors.newFixedThreadPool(q); List<Callable<String>> callableTasks = new ArrayList<>(); // operations for (int i = 0; i < q; i++) { // parse the string. String[] parsed = queries2[i].split("\\s"); int operationCode = Integer.parseInt(parsed[0])-1; String value = parsed[1]; int userId = Integer.parseInt(parsed[2]); callableTasks.add(() -> switch (operationCode) { case 0 -> object.verboseLock(value, userId); case 1 -> object.verboseUnlock(value, userId); case 2 -> object.verboseUpgrade(value, userId); default -> "INVALID"; } ); } // List<Future<Boolean>> futureResults = new ArrayList<>(); // try { // futureResults = executors.invokeAll(callableTasks); // } catch (InterruptedException e) { // System.err.println("ERROR : " + e.getLocalizedMessage()); // e.printStackTrace(); // } // // List<Boolean> results = new ArrayList<>(); // for (Future<Boolean> futureResult : futureResults) { // boolean res = false; // try { // res = futureResult.get(500, TimeUnit.MILLISECONDS); // } catch (Exception e) { // System.err.println("error : " + e.getLocalizedMessage()); // e.printStackTrace(); // } // results.add(res); // } // testing. List<Future<String>> futureResults = new ArrayList<>(); try { futureResults = executors.invokeAll(callableTasks); } catch (InterruptedException e) { System.err.println("ERROR : " + e.getLocalizedMessage()); e.printStackTrace(); } List<String> results = new ArrayList<>(); for (Future<String> futureResult : futureResults) { String res = null; try { res = futureResult.get(5000, TimeUnit.MILLISECONDS); } catch (Exception e) { System.err.println("Error : " + e.getLocalizedMessage()); e.printStackTrace(); } results.add(res); } // close the executors executors.shutdown(); try { if(!executors.awaitTermination(5, TimeUnit.SECONDS)) { executors.shutdownNow(); } } catch (Exception e) { executors.shutdownNow(); System.out.println("Error : " + e.getLocalizedMessage()); e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.err.println("Time elapsed : " + (endTime - startTime) / 1000.0 + "sec."); System.out.println("result : "); for (String res : results) { System.out.println(res); } // tests //out.println(object.lock("China", 9)); // object.printTree(root); // //out.println(object.lock("India", 9)); //object.printTree(root); // //out.println(object.upgrade("Asia", 9)); // // System.out.println(object.unlock("India", 9)); System.out.println("\nfinal state : "); object.printTree(root); // // System.out.println(object.unlock("China", 9)); // object.printTree(root); } }
Editor is loading...