// Run the AccuRev stat command for the stream and initialize our _map class variable with the results. // Returns true if the operation succeeded, false otherwise. AcUtilsException caught and logged in // %LOCALAPPDATA%\AcTools\Logs\Stranded-YYYY-MM-DD.log on stat command failure. Exception caught and // logged in same for a range of exceptions. private static async Task <bool> runStatCommandAsync(AcStream stream) { bool ret = false; // assume failure try { AcResult result = await AcCommand.runAsync($@"stat -fx -s ""{stream}"" -i"); if (result != null && result.RetVal == 0) { XElement xml = XElement.Parse(result.CmdResult); int num = xml.Elements("element").Count(); if (num > 0) { lock (_locker) { _map.Add(stream, initVal(xml)); } } } ret = true; } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.runStatCommandAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.runStatCommandAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Returns the attributes for the element in stream if the query succeeded, otherwise null. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on stat command failure. // Exception caught and logged in same for a range of exceptions. private static async Task <XElement> getElementInfoAsync(AcStream stream, string element) { XElement e = null; try { AcResult r = await AcCommand.runAsync($@"stat -fx -s ""{stream}"" ""{element}"""); if (r != null && r.RetVal == 0) { XElement xml = XElement.Parse(r.CmdResult); e = xml.Element("element"); e.AddAnnotation(stream); // add stream since it's not in the XML } } catch (AcUtilsException ecx) { AcDebug.Log($"AcUtilsException caught and logged in Program.getElementInfoAsync{Environment.NewLine}{ecx.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.getElementInfoAsync{Environment.NewLine}{ecx.Message}"); } return(e); }
// Run the stat command for streams in depots listed in LatestOverlaps.exe.config and add the // results to the Stat.Elements list. Returns true if initialization succeeded, false otherwise. // AcUtilsException caught and logged in %LOCALAPPDATA%\AcTools\Logs\LatestOverlaps-YYYY-MM-DD.log // on stat command failure. Exception caught and logged in same for a range of exceptions. private static async Task <bool> initStatAsync() { bool ret = false; // assume failure try { IEnumerable <XElement> trans = from e in _hist.Elements("transaction") select e; ILookup <string, XElement> map = trans.ToLookup(n => (string)n.Attribute("streamName"), n => n); List <Task <AcResult> > tasks = new List <Task <AcResult> >(); foreach (var ii in map) // for each stream { AcStream stream = _depots.getStream(ii.Key); if (!stream.HasDefaultGroup) { continue; // run stat only if default group exists } tasks.Add(AcCommand.runAsync($@"stat -s ""{stream}"" -o -fx")); } bool op = true; while (tasks.Count > 0 && op) { Task <AcResult> r = await Task.WhenAny(tasks); tasks.Remove(r); op = (r != null && r.Result.RetVal == 0 && Stat.init(r.Result.CmdResult)); } ret = op; // true if all completed successfully } catch (AcUtilsException exc) { AcDebug.Log($"AcUtilsException caught and logged in Program.initStatAsync{Environment.NewLine}{exc.Message}"); } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.initStatAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }
// Report evil twins if found. Assumes the initMapAsync method has been called. Exception caught // and logged in %LOCALAPPDATA%\AcTools\Logs\EvilTwins-YYYY-MM-DD.log on operation failure. private static async Task <bool> reportAsync() { bool ret = false; // assume failure try { foreach (KeyValuePair <AcDepot, HashSet <Tuple <string, int> > > pair in _map.OrderBy(n => n.Key)) // order by AcDepot { AcDepot depot = pair.Key; // depot HashSet <Tuple <string, int> > hset = pair.Value; // [element, EID] from all dynamic streams in depot // from our hashset create a collection of elements mapped to their EID's Lookup <string, Tuple <string, int> > col = (Lookup <string, Tuple <string, int> >)hset.ToLookup(n => n.Item1); // where more than one EID exists for the element, order by element foreach (var ii in col.Where(n => n.Count() > 1).OrderBy(n => n.Key)) { string element = ii.Key; if (_excludeList != null && _excludeList.Contains(element)) { continue; // ignore if in TwinsExcludeFile } log(element); IEnumerable <AcStream> filter = from n in depot.Streams where n.IsDynamic && !n.Hidden select n; List <Task <XElement> > tasks = new List <Task <XElement> >(filter.Count()); foreach (AcStream stream in filter) { tasks.Add(getElementInfoAsync(stream, element)); } XElement[] arr = await Task.WhenAll(tasks); // finish running stat commands in parallel if (arr != null && arr.All(n => n != null)) // true if all ran successfully { foreach (Tuple <string, int> jj in ii.OrderBy(n => n.Item2)) // order twins by EID { int eid = jj.Item2; log($"\tEID: {eid} on {DateTime.Now.ToString("ddd MMM d h:mm tt")}"); // C# language short-circuit: the test for id equals eid isn't evaluated if status equals "(no such elem)", // otherwise an exception would be thrown since the id attribute doesn't exist in this case foreach (XElement e in arr.Where(n => (string)n.Attribute("status") != "(no such elem)" && (int)n.Attribute("id") == eid).OrderBy(n => n.Annotation <AcStream>())) { log($"\t\t{e.Annotation<AcStream>()} {(string)e.Attribute("status")}"); string namedVersion = (string)e.Attribute("namedVersion"); // virtual stream name and version number string temp = (string)e.Attribute("Real"); string[] real = temp.Split('\\'); // workspace stream and version numbers AcStream wkspace = depot.getStream(int.Parse(real[0])); // workspace stream ElementType elemType = e.acxType("elemType"); string twin; if ((long?)e.Attribute("size") != null) { twin = $"\t\t\tSize: {(long)e.Attribute("size")}, ModTime: {e.acxTime("modTime")} {{{elemType}}}" + $"{Environment.NewLine}\t\t\tReal: {wkspace}\\{real[1]}, Virtual: {namedVersion}"; } else // a folder or link { twin = $"\t\t\tReal: {wkspace}\\{real[1]}, Virtual: {namedVersion} {{{elemType}}}"; } log(twin); } log(""); } } } } ret = true; // operation succeeded } catch (Exception ecx) { AcDebug.Log($"Exception caught and logged in Program.reportAsync{Environment.NewLine}{ecx.Message}"); } return(ret); }