/// <summary> /// Look for a parent node of the given path (if it exists) and /// ask it to refresh. This is necessary because filesystemwatcher /// doesn't always work over network shares. /// </summary> public void WatchParentOf(string path) { string parent = Path.GetDirectoryName(path); WatcherNode node = tree.NodeMap[parent] as WatcherNode; if (node != null) { node.UpdateLater(); } }
/** * Updates the state of the watcher, given reception of a new message. * * @param m * The message that was received. */ private void update(WatcherMessage m) { WatcherNode wn2; HashSet<WatcherNode> spawnedNodes; HashSet<WatcherNode> newNodes = new HashSet<WatcherNode>(); int size = 0, atoms = 0; foreach (WatcherNode wn in m_nodes) { wn2 = new WatcherNode(); wn2.setGamma(wn.getDelta()); spawnedNodes = wn2.spawn(m); foreach (WatcherNode wn3 in spawnedNodes) { newNodes.Add(wn3); } } m_nodes = newNodes; // Updates statistics about maximum number of nodes size = m_nodes.Count; if (size > m_maxNodes) { m_maxNodes = size; } // Updates statistics about total number of formulae size = 0; atoms = 0; foreach (WatcherNode wn in m_nodes) { size += wn.getSize(); atoms += wn.getAtoms(); } if (size > m_maxFormulae) { m_maxFormulae = size; } if (atoms > m_maxAtoms) { m_maxAtoms = atoms; } }
/** * Resets the watcher's state, i.e. considers the next message to be received * as the first one. */ public override void reset() { WatcherNode wn = new WatcherNode(); HashSet<Operator> hs = new HashSet<Operator>(); hs.Add(m_formulaToWatch); wn.setDelta(hs); m_nodes.Clear(); m_nodes.Add(wn); m_maxNodes = 1; m_maxFormulae = 0; m_maxAtoms = 0; }
/** * Decomposes a watcher's node, given a received message. * * @param m * The message on which to make the decomposition * @return A Set of WatcherNodes consisting of the resulting decomposition * for that node. If the left-hand side of the node is empty, * returns an empty set. */ public HashSet<WatcherNode> spawn(WatcherMessage m) { // This method uses getClass to branch on the type of operator // used; TODO: redesign with method overriding HashSet<WatcherNode> spawnedSet, outSet = new HashSet<WatcherNode>(); WatcherNode wn; Operator o2, o3; // Picks a formula and removes it from Gamma foreach (Operator o in m_gamma) { m_gamma.Remove(o); // Optimization from original algorithm: if formula can readily // be decided in current state, bypass decomposition Outcome oc = isSatisfiedInCurrentState(o, m); if (oc == Outcome.TRUE) { // Formula is true: stop decomposition of this formula and // continue spawning return spawn(m); } else if (oc == Outcome.FALSE) { // Formula is false: stop branch and return empty set return outSet; } // Operator OR else if (o.GetType() == typeof(OperatorOr)) { // Do for left operand wn = new WatcherNode(this); o2 = ((OperatorOr)o).getLeftOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } // Do for right operand wn = new WatcherNode(this); o2 = ((OperatorOr)o).getRightOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator IMPLIES else if (o.GetType() == typeof(OperatorImplies)) { // Do for right operand wn = new WatcherNode(this); o2 = ((OperatorImplies)o).getRightOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } // Do for right operand wn = new WatcherNode(this); o2 = ((OperatorImplies)o).getLeftOperand().getNegated(); wn.addToGamma(o2.getNegatedNormalForm()); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator AND else if (o.GetType() == typeof(OperatorAnd)) { // Do for left operand wn = new WatcherNode(this); o2 = ((OperatorAnd)o).getLeftOperand(); wn.addToGamma(o2); // Do for left operand o2 = ((OperatorAnd)o).getRightOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator X else if (o.GetType() == typeof(OperatorX)) { wn = new WatcherNode(this); o2 = ((OperatorX)o).getOperand(); wn.addToDelta(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator G else if (o.GetType() == typeof(OperatorG)) { // Do for left operand wn = new WatcherNode(this); o2 = ((OperatorG)o).getOperand(); wn.addToGamma(o2); wn.addToDelta(o); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator F else if (o.GetType() == typeof(OperatorF)) { // Do for left node wn = new WatcherNode(this); o2 = ((OperatorF)o).getOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } // Do for right node wn = new WatcherNode(this); wn.addToDelta(o); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator U else if (o.GetType() == typeof(OperatorU)) { // Do for left node wn = new WatcherNode(this); o2 = ((OperatorU)o).getRightOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } // Do for right node wn = new WatcherNode(this); wn.addToDelta(o); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator V else if (o.GetType() == typeof(OperatorV)) { // Do for left node wn = new WatcherNode(this); o2 = ((OperatorV)o).getLeftOperand(); wn.addToGamma(o2); o2 = ((OperatorV)o).getRightOperand(); wn.addToGamma(o2); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } // Do for right node wn = new WatcherNode(this); o2 = ((OperatorV)o).getRightOperand(); wn.addToGamma(o2); wn.addToDelta(o); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator [p=x] else if (o.GetType() == typeof(FOForAll)) { // Iterate over domain wn = new WatcherNode(this); // TODO: supposes that the string qualifier is an atom Atom p = new Atom(((FOForAll)o).getQualifier()); Atom x = ((FOForAll)o).getQuantifiedVariable(); HashSet<Atom> s = m.getDomain(p); foreach (Atom v in s) { o2 = ((FOForAll)o).getOperand(); o3 = o2.evaluate(x, v); wn.addToGamma(o3); } spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } // Operator <p=x> else if (o.GetType() == typeof(FOExists)) { // Iterate over domain // TODO: supposes that the string qualifier is an atom Atom p = new Atom(((FOExists)o).getQualifier()); Atom x = ((FOExists)o).getQuantifiedVariable(); HashSet<Atom> s = m.getDomain(p); foreach (Atom v in s) { wn = new WatcherNode(this); o2 = ((FOExists)o).getOperand(); o3 = o2.evaluate(x, v); wn.addToGamma(o3); spawnedSet = wn.spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } } // TODO (Dominic): Validate this ? return outSet; } // Operator = else if (o.GetType() == typeof(OperatorEquals)) { // This should never happen! When down to the evaluation // of an equality, all variables should be evaluated! //assert(false); return outSet; } // Operator NOT else if (o.GetType() == typeof(OperatorNot)) { // Do for operand wn = new WatcherNode(this); o2 = ((OperatorNot)o).getOperand(); if (o2.GetType() != typeof(Constant)) { // This should not happen! Negations should be pushed // to atoms //assert(false); return outSet; } // TODO: true and false are checked by comparing their // string representations; there should be a more graceful // way // to check for true and false if (((Constant)o).getSymbol() == Operator.m_trueAtom.getSymbol()) { // Constant TRUE, i.e. evaluates to FALSE: this branch // does not return anything // i.e. do nothing } else if (((Constant)o).getSymbol() == Operator.m_falseAtom.getSymbol()) { // Constant FALSE, i.e. evaluates to TRUE: just pass on // the recursive evaluation spawnedSet = spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } return outSet; } else { // This should never happen! All atoms should evaluate // down // to either true or false. System.Diagnostics.Debug.Assert (false, "Unrecognized operator in watcher node"); return outSet; } } // Constants (true or false) else if (o.GetType() == typeof(Constant)) { // TODO: true and false are checked by comparing their // string representations; there should be a more graceful // way // to check for true and false if (((Constant)o).getSymbol() == Operator.m_trueAtom.getSymbol()) { // Constant TRUE: just pass on the recursive evaluation spawnedSet = spawn(m); foreach (WatcherNode wn2 in spawnedSet) { outSet.Add(wn2); } } else if (((Constant)o).getSymbol() == Operator.m_falseAtom.getSymbol()) { // This branch is stopped: this branch does not return // anything // i.e. do nothing return outSet; } else { // This should never happen! All atoms should evaluate // down to either true or false. //assert(false); return outSet; } } } if (m_gamma.Count == 0) { // Gamma is empty: return a set with myself outSet.Add(this); } return outSet; }
/** * Constructs a WatcherNode based on another WatcherNode. (NOTE: deep or * shallow copy?) * * @param wn * The WatcherNode of which to make a copy. */ public WatcherNode(WatcherNode wn) : base(wn.getGamma(), wn.getDelta()) { }