Exemplo n.º 1
0
bool LocalCollectionQuery::
Query( const string &viewName, ExprTree *expr, bool two_way_matching )
{
	ViewRegistry::iterator	vri;
	ViewMembers::iterator	vmi;
	MatchClassAd			mad;
	View					*view;
	ClassAd					*ad=0; 
	const ClassAd			*parent;
	string					key;
	bool					match;
    bool                    given_classad=false;
    
	if (expr && expr->isClassad(&ad))
	{
		given_classad = true;
	}

    parent = NULL;

	// get the view to query
	if( !collection || ( vri = collection->viewRegistry.find( viewName ) ) == 
			collection->viewRegistry.end( ) ) {
		return( false );
	}
	view = vri->second;

	if( expr ) {
        if (given_classad) {
            mad.ReplaceLeftAd(ad);
        } else {
            // setup evluation environment if a constraint was supplied
            parent = expr->GetParentScope( );
            if( !( ad=mad.GetLeftAd() ) || !ad->Insert(ATTR_REQUIREMENTS,expr,false ) ) {
                expr->SetParentScope( parent );
                return( false );
            }
        }
	}
	keys.clear( );


	// iterate over the view members
	for( vmi=view->viewMembers.begin(); vmi!=view->viewMembers.end(); vmi++ ) {
		// ... and insert keys into local list in same order
		vmi->GetKey( key );

		if( expr ) {
			// if a constraint was supplied, make sure its satisfied
			ad = collection->GetClassAd( key );
			mad.ReplaceRightAd( ad );
			if( mad.EvaluateAttrBool( "RightMatchesLeft", match ) && match ) {
                bool add_key;
                if (!given_classad || !two_way_matching) {
                    add_key = true;
                } else if (mad.EvaluateAttrBool( "LeftMatchesRight", match ) && match) {
                    add_key = true;
                } else {
                    add_key = false;
                }
                if (add_key) {   
                    keys.push_back( key );
                }
			}
			mad.RemoveRightAd( );
		} else {
			keys.push_back( key );
		}
	}

	// initialize local iterator
	itr = keys.begin( );

	// clean up and return
	if( expr ) {
        if (given_classad) {
            mad.RemoveLeftAd();
        }
		expr->SetParentScope( parent );
		ad = mad.GetLeftAd();
		if (ad != NULL) {
			ad->Remove(ATTR_REQUIREMENTS);
		}
	}
	return( true );
}
Exemplo n.º 2
0
bool 
doMatch(const char *name, const ArgumentList &arguments, EvalState &state, Value &result)
{
  bool  eval_successful = false;
  result.SetErrorValue();
  
  // We check to make sure that we passed exactly two arguments...
  if (arguments.size() == 2) {
    Value    arg1;
    const ExprList *adList;
    // ...the first argument should evaluate to a list...
    if (arguments[0] -> Evaluate(state, arg1) &&
	arg1.IsListValue(adList)) {
      
      // ...the second argument should be either an expression 
      // operand node or a function call node...
      if (arguments[1] -> GetKind() == ExprTree::OP_NODE ||
	  arguments[1] -> GetKind() == ExprTree::FN_CALL_NODE) {
	
	// Now we prepare the match context used while looking for 
	// any matching ad in the adList.In order to evaluate correctly 
	// any attribute reference involved in the second argument we 
	// should use the same classad containing the anyMatch statement 
	// while matching. Moreover we should make a copy of the requirements 
	// expression passed as second argument and set the parent scope by 
	// inserting it into the just copied classad. Finally, we set the left
	// context which will be constant for any further match.
	MatchClassAd match;
	ClassAd* al = static_cast<classad::ClassAd*>(arguments[1]->GetParentScope()->Copy());
	al->Insert("requirements", arguments[1]->Copy());
	match.ReplaceLeftAd(al);

	std::vector<ExprTree*> ads, matching;
	adList->GetComponents(ads);
       
	for(std::vector<ExprTree*>::const_iterator it = ads.begin(); 
	    it != ads.end(); it++) {
	  
	  // Each expression in the list should be a classad...
	  if (!utils::is_classad(*it)) {
	    
	    result.SetErrorValue();
	    eval_successful = false;
	    break;
	  }

	  ClassAd* ar = static_cast<ClassAd*>((*it)->Copy());
	  match.ReplaceRightAd(ar);
	  
	  // If requirements does not evaluate to a boolean there is
	  // something seriously wrong and exit...
	  if (!match.EvaluateAttrBool("rightMatchesLeft", eval_successful)) {
	    
	    result.SetErrorValue();
	    eval_successful = false;
	    break;
	  }
	  // ...otherwise we have to set the result and exit depending 
	  // on which function was called.
	  if ( (!strcasecmp(name, "anyMatch") &&  eval_successful) ||
	       (!strcasecmp(name, "allMatch") && !eval_successful)) {
	    
	    result.SetBooleanValue(eval_successful);
	    break;
	  }
	  
	  if (!strcasecmp(name, "whichMatch") && eval_successful) {
	    
	    matching.push_back(dynamic_cast<ClassAd*>(*it));
	  }
	}
	// if the whichMatch was called we have to set the result to 
	// the classad which matched...
	if (!strcasecmp(name, "whichMatch")) {
	  
	  eval_successful = !matching.empty();
	  
	  // if there is no matching ad then the evaluation was successful
	  // and we have to set the result to undefined...
	  // ...otherwise we have to set the result to the matching ad(s)
	  if (!eval_successful) result.SetUndefinedValue();
	  else result.SetListValue(ExprList::MakeExprList(matching));
	}
      }
    }
  }
  return eval_successful;
}