Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.
  */
 
 package org.apache.pig.newplan.optimizer;
 
 import java.util.List;
 import java.util.Set;
 
Rules describe a pattern of operators. They also reference a Transformer. If the pattern of operators is found one or more times in the provided plan, then the optimizer will use the associated Transformer to transform the plan. Note: the pattern matching logic implemented here has a limitation that it assumes that all the leaves in the pattern are siblings. See more detailed description here - https://issues.apache.org/jira/browse/PIG-1742 If new rules use patterns that don't work with this limitation, the pattern match logic will need to be updated.
 
 public abstract class Rule {
 
     protected String name = null;
     protected OperatorPlan pattern;
     transient protected OperatorPlan currentPlan;
     protected static final Log log = LogFactory.getLog(Rule.class);
     private transient Set<OperatormatchedNodes = new HashSet<Operator>();
     private boolean mandatory;
     private boolean skipListener = false;
    
    
Create this rule by using the default pattern that this rule provided

Parameters:
n Name of this rule
mandatory if it is set to false, this rule can be disabled by user
 
     public Rule(String nboolean mandatory) {
          = n;    
          = buildPattern();
         this. = mandatory;
     }
    
    

Parameters:
n Name of this rule
p Pattern to look for.
 
     public Rule(String nOperatorPlan p) {
          = n;    
          = p;
     }

    
Build the pattern that this rule will look for

Returns:
the pattern to look for by this rule
 
     abstract protected OperatorPlan buildPattern();
    
    
Get the transformer for this rule. Abstract because the rule may want to choose how to instantiate the transformer. This should never return a cached transformer, it should always return a fresh one with no state.

Returns:
Transformer to use with this rule
 
     abstract public Transformer getNewTransformer(); 
    
    
Return the pattern to be matched for this rule

Returns:
the pattern to be matched for this rule
 
     public OperatorPlan getPattern() {
         return ;
     }
     
    protected boolean isSkipListener() {
        return this.;
    }
    
    protected void setSkipListener(boolean skip) {
        this. = skip;
    }
    
    
Search for all the sub-plans that matches the pattern defined by this rule. See class description above for limitations on the patterns supported.

Parameters:
plan the OperatorPlan to look for matches to the pattern
Returns:
A list of all matched sub-plans. The returned plans are partial views of the original OperatorPlan. Each is a sub-set of the original plan and represents the same topology as the pattern, but operators in the returned plan are the same objects as the original plan. Therefore, a call getPlan() from any node in the return plan would return the original plan.
    public List<OperatorPlanmatch(OperatorPlan planthrows FrontendException {
         = plan;
        
        List<Operatorleaves = .getSinks();
        
        Iterator<Operatoriter = plan.getOperators();
        List<OperatorPlanmatchedList = new ArrayList<OperatorPlan>();       
        .clear();
       
        while(iter.hasNext()) {
            Operator op = iter.next();
           
            // find a node that matches the first leaf of the pattern
            if (match(opleaves.get(0))) {
                List<OperatorplanOps = new ArrayList<Operator>();
                planOps.add(op);
                                
                // if there is more than 1 leaves in the pattern, we check 
                // if other leaves match the siblings of this node
                if (leaves.size()>1) {
                    boolean matched = true;
                    
                    
                    List<Operatorpreds = null;
                    preds = plan.getPredecessors(op);
                    
                    // if this node has no predecessor, it must be a root
                    if (preds == null) {
                        preds = new ArrayList<Operator>();
                        preds.add(null);
                    }
                    
                    for(Operator spreds) {
                        matched = true;
                        List<Operatorsiblings = null;
                        if (s != null) {
                            siblings = plan.getSuccessors(s);
                        }else{
                            // for a root, we get its siblings by getting all roots
                            siblings = plan.getSources();
                        }
                        int index = siblings.indexOf(op);
                        if (siblings.size()-index < leaves.size()) {
                            continue;
                        }
                    
                        
                        for(int j=1; j<leaves.size(); j++) {
                            if (!match(siblings.get(index+j), leaves.get(j))) {
                                matched = false;
                                break;
                            }
                        }     
                        
                        if (matched) {
                            for(int j=1; j<leaves.size(); j++) {
                                planOps.add(siblings.get(index+j));
                            }
                        }
                    
                    }
                   
                    // we have move on to next operator as this one doesn't have siblings to
                    // match all the leaves
                    if (!matched) {
                        continue;
                    }
                }
                
              
                PatternMatchOperatorPlan match = new PatternMatchOperatorPlan(plan);
                if (match.check(planOps)) {
                    // we find a matched pattern,
                    // add the operators into matchedNodes
                    Iterator<Operatoriter2 = match.getOperators();                      
                    while(iter2.hasNext()) {
                        Operator opt = iter2.next();
                        .add(opt);                        
                    }
                    
                    // add pattern
                    matchedList.add(match);                                                
                }
            }
        }
        
        return matchedList;
    }     
    public String getName() {
        return ;
    }
    
    public boolean isMandatory() {
        return ;
    }
    
    
Check if two operators match each other, we want to find matches that don't share nodes
    private boolean match(Operator planNodeOperator patternNode) {
        return planNode.getClass().equals(patternNode.getClass()) && !.contains(planNode);
    }
    
 
    private class PatternMatchOperatorPlan extends OperatorSubPlan {
        
        public PatternMatchOperatorPlan(OperatorPlan basePlan) {
            super(basePlan);
        }    	    	
        
        protected boolean check(List<OperatorplanOpsthrows FrontendException {
            List<OperatorpatternOps = .getSinks();
            if (planOps.size() != patternOps.size()) {
                return false;
            }
            
            for(int i=0; i<planOps.size(); i++) {
                Deque<Operators = new LinkedList<Operator>();
                if (!check(planOps.get(i), patternOps.get(i), s)) {
                    return false;
                }
                Iterator<Operatoriter = s.iterator();
                while(iter.hasNext()) {
                    add(iter.next());
                }
            }
            
            if (size() == .size()) {
                return true;
            }
            
            return false;
        }
        
        
Check if the plan operator and its sub-tree has a match to the pattern operator and its sub-tree. This algorithm only search and return one match. It doesn't recursively search for all possible matches. For example, for a plan that looks like join / \ load load if we are looking for join->load pattern, only one match will be returned instead of two, so that the matched subsets don't share nodes.
 
        private boolean check(Operator planOpOperator patternOpDeque<Operatoropersthrows FrontendException {
            if (!match(planOppatternOp)) {
                return false;
            }
                 
            // check if their predecessors match
            List<Operatorpreds1 = getBasePlan().getPredecessors(planOp);
            List<Operatorpreds2 = .getPredecessors(patternOp);
            if (preds1 == null && preds2 != null) {
                return false;
            }
            
            if (preds1 != null && preds2 != null && preds1.size() < preds2.size()) {
                return false;
            }
            
            // we've reached the root of the pattern, so a match is found
            if (preds2 == null || preds2.size() == 0) {       
                opers.push(planOp);
                return true;
            }
            
            int index = 0;            
            // look for predecessors 
            while(index < preds1.size()) {
                boolean match = true;
                if (match(preds1.get(index), preds2.get(0))) {
                    if ( (preds1.size() - index) < preds2.size()) {
                        return false;
                    }
                             
                    int oldSize = opers.size();
                    for(int i=0; i<preds2.size(); i++) {
                        if (!check(preds1.get(index+i), preds2.get(i), opers)) {
                            for(int j=opers.size(); j>oldSizej--) {
                                opers.pop();                                
                            }
                            match = false;
                            break;
                        }
                    }
                    if (match) {
                        opers.push(planOp);
                        return true;
                    }
                }
                index++;
            }
            
            return false;
        }    
    }
New to GrepCode? Check out our FAQ X