bool View:: InsertSubordinateView( ClassAdCollection *coll, ClassAd *viewInfo ) { View *newView = new View( this ); ViewMembers::iterator vmi; string key; ClassAd *ad; string name;; if( !newView ) { CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( false ); } if( viewInfo ) { viewInfo->EvaluateAttrString( ATTR_VIEW_NAME, name ); newView->evalEnviron.ReplaceLeftAd( viewInfo ); } newView->SetViewName( name ); if( !coll->RegisterView( name, newView ) ) { CondorErrMsg += "; failed to insert new view"; delete newView; return( false ); } subordinateViews.push_front( newView ); // insert current view content into new view for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) { vmi->GetKey( key ); if( ( ad = coll->GetClassAd( key ) ) == NULL ) { CLASSAD_EXCEPT( "internal error: classad %s in view but not in collection", key.c_str( ) ); } if( !newView->ClassAdInserted( coll, key, ad ) ) { CondorErrMsg += "; failed to insert content into new view"; return( false ); } } return( true ); }
bool View:: ClassAdModified( ClassAdCollection *coll, const string &key, ClassAd *mad ) { bool match, wasMember, sameRank, rval = true; Value rankValue, oldAdRank, equal; MemberIndex::iterator itr = memberIndex.find( key ); // check if classad is currently a member of this view if( itr == memberIndex.end( ) ) { wasMember = false; } else { wasMember = true; ((ViewMember) *(itr->second)).GetRankValue( oldAdRank ); } // evaluate constraint and get new rank value evalEnviron.ReplaceRightAd( mad ); match = evalEnviron.EvaluateAttrBool("RightMatchesLeft",match) && match; if( !evalEnviron.EvaluateAttr( "LeftRankValue", rankValue ) ) { rankValue.SetUndefinedValue( ); } evalEnviron.RemoveRightAd( ); if( wasMember && match ) { string sig; // was and still is a member; check if rank has changed Operation::Operate( Operation::IS_OP, rankValue, oldAdRank, equal ); if( !equal.IsBooleanValue( sameRank ) || !sameRank ) { // rank changed ... need to re-order ViewMember vm; // remove old view member ... vm.SetRankValue( oldAdRank ); vm.SetKey(key); viewMembers.erase( vm ); // re-insert with new rank value and update member index vm.SetRankValue( rankValue ); memberIndex[key] = viewMembers.insert( vm ); } // check if the signature has changed sig = makePartitionSignature( mad ); if( sig != oldAdSignature ) { PartitionedViews::iterator mi; View *newPartition; // yes ... remove from old partition and insert into new if( !oldAdSignature.empty( ) ) { mi = partitionedViews.find( oldAdSignature ); if( mi == partitionedViews.end( ) ) { // partition of ad not found; some internal error CLASSAD_EXCEPT( "internal error: partition of classad with " "signature %s not found", oldAdSignature.c_str( ) ); } // delete from old partition mi->second->ClassAdDeleted( coll, key, mad ); } // is there a partition with the new signature? if( !sig.empty( ) ) { mi = partitionedViews.find( sig ); if( mi != partitionedViews.end( ) ) { // yes ... insert into this partition if( !mi->second->ClassAdInserted(coll, key, mad) ) { CondorErrMsg+="; failed to relocate ad on modification"; return( false ); } } else { // no ... create a new partition if( ( newPartition = new View( this ) ) == 0 ) { oldAdSignature.erase( oldAdSignature.begin( ), oldAdSignature.end( ) ); CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( false ); } if( !coll->RegisterView( viewName+":"+sig, newPartition ) ){ delete newPartition; CondorErrMsg += "; failed to create new partition for " " modified ad"; return( false ); } newPartition->SetViewName( viewName + ":" + sig ); if( !newPartition->ClassAdInserted(coll, key, mad) ) { CondorErrMsg+="; failed to relocate ad on modification"; return( false ); } partitionedViews[sig] = newPartition; } } } // send modification notification to all subordinate children SubordinateViews::iterator xi; for( xi=subordinateViews.begin( ); xi!=subordinateViews.end( ); xi++ ){ if( !(*xi)->ClassAdModified( coll, key, mad ) ) { return( false ); } } } else if( !wasMember && match ) { // wasn't a member, but now is --- insert the ad rval = ClassAdInserted( coll, key, mad ); } else if( wasMember && !match ) { // was a member, but now isnt --- delete the ad ClassAdDeleted( coll, key, mad ); rval = true; } else { // wasn't a member and still isn't --- nothing to do } oldAdSignature.erase( oldAdSignature.begin( ), oldAdSignature.end( ) ); if( !rval ) { CondorErrMsg += "; failed to modify ad"; } return( rval ); }
// The convention is that each view verifies its constraint before accepting // an ad. However, the view assumes that in the case of view partitions, the // parent view will have identified the correct child partition to use. bool View:: ClassAdInserted( ClassAdCollection *coll, const string &key, ClassAd *ad ) { PartitionedViews::iterator partition; string signature; ViewMember vm; bool match; Value rankValue; View *childView; // check if the ad satisfies the view's constraint; if the constraint // was not satisfied, the ad can be ignored evalEnviron.ReplaceRightAd( ad ); match = evalEnviron.EvaluateAttrBool("RightMatchesLeft",match) && match; if( !match ) { evalEnviron.RemoveRightAd( ); return( true ); } // obtain the rank value of the ad if( !evalEnviron.EvaluateAttr( "LeftRankValue", rankValue ) ) { CondorErrMsg += "; could not get 'Rank' value; failed to insert " "classad " + key + "in view " + viewName; return( false ); } evalEnviron.RemoveRightAd( ); // insert into every subordinate child view SubordinateViews::iterator xi; for( xi = subordinateViews.begin( ); xi != subordinateViews.end( ); xi++ ) { if( !(*xi)->ClassAdInserted( coll, key, ad ) ) { return( false ); } } // find partition to insert into signature = makePartitionSignature( ad ); if( !signature.empty( ) ) { partition = partitionedViews.find( signature ); if( partition == partitionedViews.end( ) ) { // no appropriate partition --- create one and insert if( ( childView = new View( this ) ) == 0 ) { CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( false ); } if( !coll->RegisterView( viewName + ":" + signature, childView ) ) { if( childView ) delete childView; CondorErrMsg += "; failed to create view; failed to insert " "classad " + key + "in view"; return( false ); } childView->SetViewName( viewName + ":" + signature ); partitionedViews[signature] = childView; } else { childView = partitionedViews[signature]; } // update the partition if( !childView->ClassAdInserted( coll, key, ad ) ) { return( false ); } } // insert ad into list of view members and update index vm.SetKey( key ); vm.SetRankValue( rankValue ); memberIndex[key] = viewMembers.insert(vm); return( true ); }
bool View:: SetPartitionExprs( ClassAdCollection *coll, ExprList *el ) { // insert expression list into view info ClassAd *ad = evalEnviron.GetLeftAd( ); if( !el ) { CondorErrno = ERR_BAD_PARTITION_EXPRS; CondorErrMsg = "invalid 'PartitionExprs'; failed to partition"; return( false ); } if( !( ad->Insert( ATTR_PARTITION_EXPRS, (ExprTree* &)el ) ) ) { CondorErrMsg += "failed to set partition expressions on view"; return( false ); } // re-establish partition views; first delete all partition views PartitionedViews::iterator mi; for( mi = partitionedViews.begin( ); mi != partitionedViews.end( ); mi++ ) { mi->second->DeleteView( coll ); delete mi->second; } partitionedViews.clear( ); // if the partition expressions list is empty, we're done vector<ExprTree*> components; el->GetComponents( components ); if( components.size( ) == 0 ) return( true ); // re-partition content ViewMembers::iterator vmi; string key, signature; View *partition; for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) { // get signature of this ad vmi->GetKey( key ); if( ( ad = coll->GetClassAd( key ) ) == NULL ) { CLASSAD_EXCEPT( "internal error: classad %s in view but not in collection", key.c_str( ) ); } signature = makePartitionSignature( ad ); // check if we have a partition with this signature if( partitionedViews.find( signature ) == partitionedViews.end( ) ) { // no partition ... make a new one if( ( partition = new View( this ) ) == NULL ) { CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( false ); } if( !coll->RegisterView( viewName + ":" + signature, partition ) ) { CondorErrMsg += "; could not complete partitioning"; return( false ); } partition->SetViewName( viewName + ":" + signature ); partitionedViews[signature] = partition; } else { // use the partition that's already there partition = partitionedViews[signature]; } // add classad to the partition if( !partition->ClassAdInserted( coll, key, ad ) ) { CondorErrMsg += "; failed to set partition expressions"; return( false ); } } return( true ); }