public static void Main(string[] args) { var p = InitProps(); Config conf = new Config(p); PerfRunData runData = new PerfRunData(conf); // 1. top sequence TaskSequence top = new TaskSequence(runData, null, null, false); // top level, not parallel // 2. task to create the index CreateIndexTask create = new CreateIndexTask(runData); top.AddTask(create); // 3. task seq to add 500 docs (order matters - top to bottom - add seq to top, only then add to seq) TaskSequence seq1 = new TaskSequence(runData, "AddDocs", top, false); seq1.SetRepetitions(500); seq1.SetNoChildReport(); top.AddTask(seq1); // 4. task to add the doc AddDocTask addDoc = new AddDocTask(runData); //addDoc.setParams("1200"); // doc size limit if supported seq1.AddTask(addDoc); // order matters 9see comment above) // 5. task to close the index CloseIndexTask close = new CloseIndexTask(runData); top.AddTask(close); // task to report RepSumByNameTask rep = new RepSumByNameTask(runData); top.AddTask(rep); // print algorithm Console.WriteLine(top.ToString()); // execute top.DoLogic(); }
/// <summary> /// Read algorithm from file. /// Property examined: alt.tasks.packages == comma separated list of /// alternate Assembly names where tasks would be searched for, when not found /// in the default Assembly (that of <see cref="PerfTask"/>). /// If the same task class appears in more than one Assembly, the Assembly /// indicated first in this list will be used. /// <para/> /// The Lucene.Net implementation differs from Lucene in that all /// referenced assemblies are also scanned for the type. However, /// alt.tasks.packages may be included for assemblies that are /// not referenced in your project. /// </summary> /// <param name="runData">perf-run-data used at running the tasks.</param> /// <exception cref="Exception">if errors while parsing the algorithm.</exception> public Algorithm(PerfRunData runData) { Config config = runData.Config; taskPackages = InitTasksPackages(config); string algTxt = config.AlgorithmText; sequence = new TaskSequence(runData, null, null, false); TaskSequence currSequence = sequence; PerfTask prevTask = null; StreamTokenizer stok = new StreamTokenizer(new StringReader(algTxt)); stok.CommentChar('#'); stok.IsEOLSignificant = false; stok.QuoteChar('"'); stok.QuoteChar('\''); stok.OrdinaryChar('/'); stok.OrdinaryChar('('); stok.OrdinaryChar(')'); bool colonOk = false; bool isDisableCountNextTask = false; // only for primitive tasks currSequence.Depth = 0; while (stok.NextToken() != StreamTokenizer.TT_EOF) { switch (stok.TokenType) { case StreamTokenizer.TT_WORD: string s = stok.StringValue; PerfTask task = (PerfTask)Activator.CreateInstance(TaskClass(config, s), runData); task.AlgLineNum = stok.LineNumber; task.DisableCounting = isDisableCountNextTask; isDisableCountNextTask = false; currSequence.AddTask(task); if (task is RepSumByPrefTask) { stok.NextToken(); string prefix = stok.StringValue; if (prefix == null || prefix.Length == 0) { throw new Exception("named report prefix problem - " + stok.ToString()); } ((RepSumByPrefTask)task).SetPrefix(prefix); } // check for task param: '(' someParam ')' stok.NextToken(); if (stok.TokenType != '(') { stok.PushBack(); } else { // get params, for tasks that supports them - allow recursive parenthetical expressions stok.IsEOLSignificant = true; // Allow params tokenizer to keep track of line number StringBuilder @params = new StringBuilder(); stok.NextToken(); if (stok.TokenType != ')') { int count = 1; while (true) { switch (stok.TokenType) { case StreamTokenizer.TT_NUMBER: { @params.Append(stok.NumberValue); break; } case StreamTokenizer.TT_WORD: { @params.Append(stok.StringValue); break; } case StreamTokenizer.TT_EOF: { throw new Exception("Unexpexted EOF: - " + stok.ToString()); } case '"': case '\'': { @params.Append((char)stok.TokenType); // re-escape delimiters, if any @params.Append(stok.StringValue.Replace("" + (char)stok.TokenType, @"\" + (char)stok.TokenType)); @params.Append((char)stok.TokenType); break; } case '(': { @params.Append((char)stok.TokenType); ++count; break; } case ')': { if (--count >= 1) { // exclude final closing parenthesis @params.Append((char)stok.TokenType); } else { goto BALANCED_PARENS_BREAK; } break; } default: { @params.Append((char)stok.TokenType); break; } } stok.NextToken(); } BALANCED_PARENS_BREAK : { } } stok.IsEOLSignificant = false; string prm = @params.ToString().Trim(); if (prm.Length > 0) { task.SetParams(prm); } } // --------------------------------------- colonOk = false; prevTask = task; break; default: char c = (char)stok.TokenType; switch (c) { case ':': if (!colonOk) { throw new Exception("colon unexpexted: - " + stok.ToString()); } colonOk = false; // get repetitions number stok.NextToken(); if ((char)stok.TokenType == '*') { ((TaskSequence)prevTask).SetRepetitions(TaskSequence.REPEAT_EXHAUST); } else { if (stok.TokenType != StreamTokenizer.TT_NUMBER) { throw new Exception("expected repetitions number or XXXs: - " + stok.ToString()); } else { double num = stok.NumberValue; stok.NextToken(); if (stok.TokenType == StreamTokenizer.TT_WORD && stok.StringValue.Equals("s", StringComparison.Ordinal)) { ((TaskSequence)prevTask).SetRunTime(num); } else { stok.PushBack(); ((TaskSequence)prevTask).SetRepetitions((int)num); } } } // check for rate specification (ops/min) stok.NextToken(); if (stok.TokenType != ':') { stok.PushBack(); } else { // get rate number stok.NextToken(); if (stok.TokenType != StreamTokenizer.TT_NUMBER) { throw new Exception("expected rate number: - " + stok.ToString()); } // check for unit - min or sec, sec is default stok.NextToken(); if (stok.TokenType != '/') { stok.PushBack(); ((TaskSequence)prevTask).SetRate((int)stok.NumberValue, false); // set rate per sec } else { stok.NextToken(); if (stok.TokenType != StreamTokenizer.TT_WORD) { throw new Exception("expected rate unit: 'min' or 'sec' - " + stok.ToString()); } string unit = stok.StringValue.ToLowerInvariant(); if ("min".Equals(unit, StringComparison.Ordinal)) { ((TaskSequence)prevTask).SetRate((int)stok.NumberValue, true); // set rate per min } else if ("sec".Equals(unit, StringComparison.Ordinal)) { ((TaskSequence)prevTask).SetRate((int)stok.NumberValue, false); // set rate per sec } else { throw new Exception("expected rate unit: 'min' or 'sec' - " + stok.ToString()); } } } colonOk = false; break; case '{': case '[': // a sequence // check for sequence name string name = null; stok.NextToken(); if (stok.TokenType != '"') { stok.PushBack(); } else { name = stok.StringValue; if (stok.TokenType != '"' || name == null || name.Length == 0) { throw new Exception("sequence name problem - " + stok.ToString()); } } // start the sequence TaskSequence seq2 = new TaskSequence(runData, name, currSequence, c == '['); currSequence.AddTask(seq2); currSequence = seq2; colonOk = false; break; case '&': if (currSequence.IsParallel) { throw new Exception("Can only create background tasks within a serial task"); } stok.NextToken(); int deltaPri; if (stok.TokenType != StreamTokenizer.TT_NUMBER) { stok.PushBack(); deltaPri = 0; } else { // priority deltaPri = (int)stok.NumberValue; } if (prevTask == null) { throw new Exception("& was unexpected"); } else if (prevTask.RunInBackground) { throw new Exception("double & was unexpected"); } else { prevTask.SetRunInBackground(deltaPri); } break; case '>': currSequence.SetNoChildReport(); /* intentional fallthrough */ // end sequence colonOk = true; prevTask = currSequence; currSequence = currSequence.Parent; break; case '}': case ']': // end sequence colonOk = true; prevTask = currSequence; currSequence = currSequence.Parent; break; case '-': isDisableCountNextTask = true; break; } //switch(c) break; } //switch(stok.ttype) } if (sequence != currSequence) { throw new Exception("Unmatched sequences"); } // remove redundant top level enclosing sequences while (sequence.IsCollapsable && sequence.Repetitions == 1 && sequence.GetRate() == 0) { IList <PerfTask> t = sequence.Tasks; if (t != null && t.Count == 1) { PerfTask p = t[0]; if (p is TaskSequence) { sequence = (TaskSequence)p; continue; } } break; } }