pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / benchmark / src / java / org / apache / lucene / benchmark / byTask / utils / Algorithm.java
diff --git a/lucene-java-3.5.0/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Algorithm.java b/lucene-java-3.5.0/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Algorithm.java
new file mode 100644 (file)
index 0000000..0d6ff80
--- /dev/null
@@ -0,0 +1,333 @@
+package org.apache.lucene.benchmark.byTask.utils;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.lucene.benchmark.byTask.PerfRunData;
+import org.apache.lucene.benchmark.byTask.tasks.PerfTask;
+import org.apache.lucene.benchmark.byTask.tasks.RepSumByPrefTask;
+import org.apache.lucene.benchmark.byTask.tasks.TaskSequence;
+
+/**
+ * Test algorithm, as read from file
+ */
+public class Algorithm {
+  
+  private TaskSequence sequence;
+  private final String[] taskPackages;
+  
+  /**
+   * Read algorithm from file
+   * Property examined: alt.tasks.packages == comma separated list of 
+   * alternate package names where tasks would be searched for, when not found 
+   * in the default package (that of {@link PerfTask}{@link #getClass()}).
+   * If the same task class appears in more than one package, the package 
+   * indicated first in this list will be used.
+   * @param runData perf-run-data used at running the tasks.
+   * @throws Exception if errors while parsing the algorithm 
+   */
+  @SuppressWarnings("fallthrough")
+  public Algorithm (PerfRunData runData) throws Exception {
+    Config config = runData.getConfig();
+    taskPackages = initTasksPackages(config);
+    String algTxt = config.getAlgorithmText();
+    sequence = new TaskSequence(runData,null,null,false);
+    TaskSequence currSequence = sequence;
+    PerfTask prevTask = null;
+    StreamTokenizer stok = new StreamTokenizer(new StringReader(algTxt));
+    stok.commentChar('#');
+    stok.eolIsSignificant(false);
+    stok.ordinaryChar('"');
+    stok.ordinaryChar('/');
+    stok.ordinaryChar('(');
+    stok.ordinaryChar(')');
+    boolean colonOk = false; 
+    boolean isDisableCountNextTask = false; // only for primitive tasks
+    currSequence.setDepth(0);
+    
+    while (stok.nextToken() != StreamTokenizer.TT_EOF) { 
+      switch(stok.ttype) {
+  
+        case StreamTokenizer.TT_WORD:
+          String s = stok.sval;
+          Constructor<? extends PerfTask> cnstr = taskClass(config,s)
+            .asSubclass(PerfTask.class).getConstructor(PerfRunData.class);
+          PerfTask task = cnstr.newInstance(runData);
+          task.setDisableCounting(isDisableCountNextTask);
+          isDisableCountNextTask = false;
+          currSequence.addTask(task);
+          if (task instanceof RepSumByPrefTask) {
+            stok.nextToken();
+            String prefix = stok.sval;
+            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.ttype!='(') {
+            stok.pushBack();
+          } else {
+            // get params, for tasks that supports them, - anything until next ')'
+            StringBuilder params = new StringBuilder();
+            stok.nextToken();
+            while (stok.ttype!=')') { 
+              switch (stok.ttype) {
+                case StreamTokenizer.TT_NUMBER:  
+                  params.append(stok.nval);
+                  break;
+                case StreamTokenizer.TT_WORD:    
+                  params.append(stok.sval);             
+                  break;
+                case StreamTokenizer.TT_EOF:     
+                  throw new Exception("unexpexted EOF: - "+stok.toString());
+                default:
+                  params.append((char)stok.ttype);
+              }
+              stok.nextToken();
+            }
+            String prm = params.toString().trim();
+            if (prm.length()>0) {
+              task.setParams(prm);
+            }
+          }
+
+          // ---------------------------------------
+          colonOk = false; prevTask = task;
+          break;
+  
+        default:
+          char c = (char)stok.ttype;
+          
+          switch(c) {
+          
+            case ':' :
+              if (!colonOk) throw new Exception("colon unexpexted: - "+stok.toString());
+              colonOk = false;
+              // get repetitions number
+              stok.nextToken();
+              if ((char)stok.ttype == '*') {
+                ((TaskSequence)prevTask).setRepetitions(TaskSequence.REPEAT_EXHAUST);
+              } else {
+                if (stok.ttype!=StreamTokenizer.TT_NUMBER)  {
+                  throw new Exception("expected repetitions number or XXXs: - "+stok.toString());
+                } else {
+                  double num = stok.nval;
+                  stok.nextToken();
+                  if (stok.ttype == StreamTokenizer.TT_WORD && stok.sval.equals("s")) {
+                    ((TaskSequence) prevTask).setRunTime(num);
+                  } else {
+                    stok.pushBack();
+                    ((TaskSequence) prevTask).setRepetitions((int) num);
+                  }
+                }
+              }
+              // check for rate specification (ops/min)
+              stok.nextToken();
+              if (stok.ttype!=':') {
+                stok.pushBack();
+              } else {
+                // get rate number
+                stok.nextToken();
+                if (stok.ttype!=StreamTokenizer.TT_NUMBER) throw new Exception("expected rate number: - "+stok.toString());
+                // check for unit - min or sec, sec is default
+                stok.nextToken();
+                if (stok.ttype!='/') {
+                  stok.pushBack();
+                  ((TaskSequence)prevTask).setRate((int)stok.nval,false); // set rate per sec
+                } else {
+                  stok.nextToken();
+                  if (stok.ttype!=StreamTokenizer.TT_WORD) throw new Exception("expected rate unit: 'min' or 'sec' - "+stok.toString());
+                  String unit = stok.sval.toLowerCase();
+                  if ("min".equals(unit)) {
+                    ((TaskSequence)prevTask).setRate((int)stok.nval,true); // set rate per min
+                  } else if ("sec".equals(unit)) {
+                    ((TaskSequence)prevTask).setRate((int)stok.nval,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.ttype!='"') {
+                stok.pushBack();
+              } else {
+                stok.nextToken();
+                name = stok.sval;
+                stok.nextToken();
+                if (stok.ttype!='"' || 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();
+              final int deltaPri;
+              if (stok.ttype != StreamTokenizer.TT_NUMBER) {
+                stok.pushBack();
+                deltaPri = 0;
+              } else {
+                // priority
+                deltaPri = (int) stok.nval;
+              }
+
+              if (prevTask == null) {
+                throw new Exception("& was unexpected");
+              } else if (prevTask.getRunInBackground()) {
+                throw new Exception("double & was unexpected");
+              } else {
+                prevTask.setRunInBackground(deltaPri);
+              }
+              break;
+    
+            case '>' :
+              currSequence.setNoChildReport(); /* intentional fallthrough */
+            case '}' : 
+            case ']' : 
+              // end sequence
+              colonOk = true; prevTask = currSequence;
+              currSequence = currSequence.getParent();
+              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.getRepetitions()==1 && sequence.getRate()==0) {
+      ArrayList<PerfTask> t = sequence.getTasks();
+      if (t!=null && t.size()==1) {
+        PerfTask p = t.get(0);
+        if (p instanceof TaskSequence) {
+          sequence = (TaskSequence) p;
+          continue;
+        }
+      }
+      break;
+    }
+  }
+
+  private String[] initTasksPackages(Config config) {
+    String alts = config.get("alt.tasks.packages", null);
+    String dfltPkg = PerfTask.class.getPackage().getName();
+    if (alts==null) {
+      return new String[]{ dfltPkg };
+    }
+    ArrayList<String> pkgs = new ArrayList<String>();
+    pkgs.add(dfltPkg);
+    for (String alt : alts.split(",")) {
+      pkgs.add(alt);
+    }
+    return pkgs.toArray(new String[0]);
+  }
+
+  private Class<?> taskClass(Config config, String taskName)
+      throws ClassNotFoundException {
+    for (String pkg : taskPackages) {
+      try {
+        return Class.forName(pkg+'.'+taskName+"Task");
+      } catch (ClassNotFoundException e) {
+        // failed in this package, might succeed in the next one... 
+      }
+    }
+    // can only get here if failed to instantiate
+    throw new ClassNotFoundException(taskName+" not found in packages "+Arrays.toString(taskPackages));
+  }
+
+  @Override
+  public String toString() {
+    String newline = System.getProperty("line.separator");
+    StringBuilder sb = new StringBuilder();
+    sb.append(sequence.toString());
+    sb.append(newline);
+    return sb.toString();
+  }
+
+  /**
+   * Execute this algorithm
+   * @throws Exception 
+   */
+  public void execute() throws Exception {
+    try {
+      sequence.runAndMaybeStats(true);
+    } finally {
+      sequence.close();
+    }
+  }
+
+  /**
+   * Expert: for test purposes, return all tasks participating in this algorithm.
+   * @return all tasks participating in this algorithm.
+   */
+  public ArrayList<PerfTask> extractTasks() {
+    ArrayList<PerfTask> res = new ArrayList<PerfTask>();
+    extractTasks(res, sequence);
+    return res;
+  }
+  private void extractTasks (ArrayList<PerfTask> extrct, TaskSequence seq) {
+    if (seq==null) 
+      return;
+    extrct.add(seq);
+    ArrayList<PerfTask> t = sequence.getTasks();
+    if (t==null) 
+      return;
+    for (final PerfTask p : t) {
+      if (p instanceof TaskSequence) {
+        extractTasks(extrct, (TaskSequence)p);
+      } else {
+        extrct.add(p);
+      }
+    }
+  }
+  
+}
+