예제 #1
0
파일: util.cpp 프로젝트: AlainRoy/htcondor
bool
caInsert( ClassAd* target, ClassAd* source, const char* attr,
		  const char* prefix )
{
	ExprTree* tree;

	if( !attr ) {
		EXCEPT( "caInsert called with NULL attribute" );
	}
	if( !target || !source ) {
		EXCEPT( "caInsert called with NULL classad" );
	}

	MyString new_attr;
	if( prefix ) {
		new_attr = prefix;
	}
	new_attr += attr;

	tree = source->LookupExpr( attr );
	if( !tree ) {
		target->Delete(new_attr.Value());
		return false;
	}
	tree = tree->Copy();
	if ( !target->Insert(new_attr.Value(), tree, false) ) {
		dprintf( D_ALWAYS, "caInsert: Can't insert %s into target classad.\n", attr );
		delete tree;
		return false;
	}
	return true;
}
예제 #2
0
bool AttributeReference::
_Evaluate (EvalState &state, Value &val, ExprTree *&sig ) const
{
	ExprTree	*tree;
	ExprTree	*exprSig;
	const ClassAd *curAd;
	bool		rval;

	curAd = state.curAd;
	exprSig = NULL;
	rval 	= true;

	switch( FindExpr( state , tree , exprSig , true ) ) {
		case EVAL_FAIL:
			rval = false;
			break;

		case EVAL_ERROR:
			val.SetErrorValue( );
			break;

		case EVAL_UNDEF:
			val.SetUndefinedValue( );
			break;

		case EVAL_OK:
		{
			if( state.depth_remaining <= 0 ) {
				val.SetErrorValue();
				state.curAd = curAd;
				return false;
			}
			state.depth_remaining--;

			rval = tree->Evaluate( state, val );

			state.depth_remaining++;

			break;
		}
		default:  CLASSAD_EXCEPT( "ClassAd:  Should not reach here" );
	}
	if(!rval || !(sig=new AttributeReference(exprSig,attributeStr,absolute))){
		if( rval ) {
			CondorErrno = ERR_MEM_ALLOC_FAILED;
			CondorErrMsg = "";
		}
		delete exprSig;
		sig = NULL;
		return( false );
	}
	state.curAd = curAd;
	return rval;
}
예제 #3
0
void ParametricAd::addUserTag ( const std::string& attr_name,  const std::string& attr_value){
	ExprTree* tree = Lookup ( JDL::USERTAGS  ) ;
	if ( tree ==NULL){
		// UserTags attribute has still to be created
		ClassAd ad ;
		ad.InsertAttr ( attr_name , attr_value ) ;
		ExprTree* tmp_expr = ad.Copy();
		Insert ( JDL::USERTAGS  , tmp_expr ) ;
	}else{
		// Already Existing UserTags attribute
		if (  tree->GetKind () == classad::ExprTree::CLASSAD_NODE  )
			((ClassAd*)tree)->InsertAttr ( attr_name , attr_value  ) ;
	}
}
예제 #4
0
bool AttributeReference::
_Evaluate (EvalState &state, Value &val) const
{
	ExprTree	*tree; 
	ExprTree	*dummy;
	const ClassAd *curAd;
	bool		rval;

	// find the expression and the evalstate
	curAd = state.curAd;
	switch( FindExpr( state, tree, dummy, false ) ) {
		case EVAL_FAIL:
			return false;

		case EVAL_ERROR:
			val.SetErrorValue();
			state.curAd = curAd;
			return true;

		case EVAL_UNDEF:
			val.SetUndefinedValue();
			state.curAd = curAd;
			return true;

		case EVAL_OK: 
		{
			if( state.depth_remaining <= 0 ) {
				val.SetErrorValue();
				state.curAd = curAd;
				return false;
			}
			state.depth_remaining--;

			rval = tree->Evaluate( state, val );

			state.depth_remaining++;

			state.curAd = curAd;

			return rval;
		}
		default:  CLASSAD_EXCEPT( "ClassAd:  Should not reach here" );
	}
	return false;
}
예제 #5
0
void
HookPrepareJobClient::hookExited(int exit_status) {
	HookClient::hookExited(exit_status);
	if (WIFSIGNALED(exit_status) || WEXITSTATUS(exit_status) != 0) {
		MyString status_msg = "";
		statusString(exit_status, status_msg);
		int subcode;
		if (WIFSIGNALED(exit_status)) {
			subcode = -1 * WTERMSIG(exit_status);
		}
		else {
			subcode = WEXITSTATUS(exit_status);
		}
		MyString err_msg;
		err_msg.sprintf("HOOK_PREPARE_JOB (%s) failed (%s)", m_hook_path,
						status_msg.Value());
		dprintf(D_ALWAYS|D_FAILURE,
				"ERROR in StarterHookMgr::tryHookPrepareJob: %s\n",
				err_msg.Value());
		Starter->jic->notifyStarterError(err_msg.Value(), true,
							 CONDOR_HOLD_CODE_HookPrepareJobFailure, subcode);
		Starter->RemoteShutdownFast(0);
	}
	else {
			// Make an update ad from the stdout of the hook
		MyString out(*getStdOut());
		ClassAd updateAd;
		updateAd.initFromString(out.Value(), NULL);
		dprintf(D_FULLDEBUG, "Prepare hook output classad\n");
		updateAd.dPrint(D_FULLDEBUG);

			// Insert each expr from the update ad into the job ad
		updateAd.ResetExpr();
		ClassAd* job_ad = Starter->jic->jobClassAd();
		const char *name;
		ExprTree *et;
		while (updateAd.NextExpr(name, et)) {
			ExprTree *pCopy = et->Copy();
			job_ad->Insert(name, pCopy, false);
		}
		dprintf(D_FULLDEBUG, "After Prepare hook: merged job classad:\n");
		job_ad->dPrint(D_FULLDEBUG);
		Starter->jobEnvironmentReady();
	}
}
예제 #6
0
bool
MakeSignature( const ClassAd *ad, const References &refs, string &sig )
{
    References::iterator    itr;
    ExprTree                *expr;
    Value                   val;
    ClassAdUnParser         unp;

    sig = "";
    for( itr=refs.begin( ); itr!= refs.end( ); itr++ ) {
        if((expr=ad->Lookup(*itr))&&expr->GetKind()==ExprTree::LITERAL_NODE) {
            unp.Unparse( sig, expr );
        } else {
            return( false );
        }
        sig += ":";
    }

    return( true );
}
예제 #7
0
  int
  classad_evaluate_boolean_expr(const char *s_in, const classad_expr_tree t_ex,
                                int *result)
   {
    ClassAd *ad;
    ClassAdParser parser;
    
    if (s_in == NULL || t_ex == NULL || result == NULL) 
      return C_CLASSAD_INVALID_ARG;

    ExprTree *et = (ExprTree *)t_ex;

    ad = parser.ParseClassAd(s_in);
    if (ad == NULL) return C_CLASSAD_PARSE_ERROR;

    int retcod = C_CLASSAD_NO_ERROR;

    Value v;
    et->SetParentScope(ad);
    ad->EvaluateExpr(et, v);
    et->SetParentScope(NULL);

    bool tmp_res;

    if (v.IsBooleanValue( tmp_res ))
     {
      if (tmp_res) *result = 1;
      else         *result = 0;
      retcod = C_CLASSAD_NO_ERROR;
     }
    else retcod = C_CLASSAD_INVALID_VALUE;

    delete ad;  

    return retcod;
   }
예제 #8
0
void
VMRegister::requestHostClassAds(void)
{
	// find host startd daemon
	if( !m_vm_host_daemon )
		m_vm_host_daemon = vmapi_findDaemon( m_vm_host_name, DT_STARTD);

	if( !m_vm_host_daemon ) {
		dprintf( D_FULLDEBUG, "Can't find host(%s) Startd daemon\n", m_vm_host_name );
		return;
	}

	ClassAd query_ad;
	query_ad.SetMyTypeName(QUERY_ADTYPE);
	query_ad.SetTargetTypeName(STARTD_ADTYPE);
	query_ad.Assign(ATTR_REQUIREMENTS, true);

	char *addr = m_vm_host_daemon->addr();
	Daemon hstartd(DT_STARTD, addr);
	ReliSock ssock;

	ssock.timeout( VM_SOCKET_TIMEOUT );
	ssock.encode();

	if( !ssock.connect(addr) ) {
		dprintf( D_FULLDEBUG, "Failed to connect to host startd(%s)\n to get host classAd", addr);
		return;
	}

	if(!hstartd.startCommand( QUERY_STARTD_ADS, &ssock )) {
		dprintf( D_FULLDEBUG, "Failed to send QUERY_STARTD_ADS command to host startd(%s)\n", addr);
		return;
	}

	if( !query_ad.put(ssock) ) {
		dprintf(D_FULLDEBUG, "Failed to send query Ad to host startd(%s)\n", addr);
	}

	if( !ssock.end_of_message() ) {
		dprintf(D_FULLDEBUG, "Failed to send query EOM to host startd(%s)\n", addr);
	}

	// Read host classAds
	ssock.timeout( VM_SOCKET_TIMEOUT );
	ssock.decode();
	int more = 1, num_ads = 0;
	ClassAdList adList;
	ClassAd *ad;

	while (more) {
		if( !ssock.code(more) ) {
			ssock.end_of_message();
			return;
		}

		if(more) {
			ad = new ClassAd;
			if( !ad->initFromStream(ssock) ) {
				ssock.end_of_message();
				delete ad;
				return;
			}

			adList.Insert(ad);
			num_ads++;
		}
	}

	ssock.end_of_message();

	dprintf(D_FULLDEBUG, "Got %d classAds from host\n", num_ads);

	// Although we can get more than one classAd from host machine, 
	// we use only the first one classAd
	adList.Rewind();
	ad = adList.Next();

#if !defined(WANT_OLD_CLASSADS)
	ad->AddTargetRefs( TargetJobAttrs );
#endif

	// Get each Attribute from the classAd
	// added "HOST_" in front of each Attribute name
	const char *name;
	ExprTree *expr;

	ad->ResetExpr();
	while( ad->NextExpr(name, expr) ) {
		MyString attr;
		attr += "HOST_";
		attr += name;

		// Insert or Update an attribute to host_classAd in a VMRegister object
		ExprTree * pTree = expr->Copy();
		host_classad->Insert(attr.Value(), pTree, true);
	}
}
예제 #9
0
void ParametricAd::checkInputSandbox(std::vector<std::string>& extracted){
	GLITE_STACK_TRY("ParametricAd::checkInputSandbox(std::vector<std::string>&)");
	// This vector contains all ISB string extracted Values
	unsigned int iter_i = extracted.size();
	// This Vector will replace the old InputSanbox with the extracted values
	vector<ExprTree*> isVect ;
	ExprTree* isbTree = Lookup (JDL::INPUTSB);
	if (!isbTree){ /* No inputFiles found: return */ return; }
	// These variables are needed when extracting
	const string wmpURI = (hasAttribute(JDL::WMPISB_BASE_URI))? (getString(JDL::WMPISB_BASE_URI)):"";
	const string isbURI=   (hasAttribute(JDL::ISB_BASE_URI))  ? (getString(JDL::ISB_BASE_URI)   ):"";
	Value val ;
	string isb ;
	EvaluateExpr(isbTree,val);
	inputRemotes.clear();
	switch ( val.GetType() ){
		case Value::UNDEFINED_VALUE:
			inputRemotes.push_back(isbTree->Copy());
			isVect.push_back(isbTree->Copy());
			break;
		case Value::STRING_VALUE:
			val.IsStringValue(isb);
			toBretrieved=extractFiles (JDL::INPUTSB, isb, extracted,
				lookInto_b,wmpURI,isbURI,extractedAd.get()) || toBretrieved;
			// put the extracted files back into the InputSandbox attribute
			for(;iter_i<extracted.size();iter_i++){	// Iterate ONLY over new value(s)
				val.SetStringValue(extracted[iter_i]);	// create classad Value
				isVect.push_back(Literal::MakeLiteral(val));	// Update ISB value
			}
			break;
		case Value::LIST_VALUE:{
			const ExprList *el;
			val.IsListValue( el );
			vector<ExprTree*> vectList ;
			el->GetComponents(vectList) ;
			for ( unsigned int i = 0; i< vectList.size() ; i++){
				if (vectList[i]->GetKind()!=ExprTree::LITERAL_NODE){
					// not a literal node
					inputRemotes.push_back( vectList[i]->Copy() );
					isVect.push_back(vectList[i]->Copy());
				}
				else if (vectList[i]->Evaluate(val)){
					switch (val.GetType()){
						case Value::STRING_VALUE:
							val.IsStringValue(isb);
							toBretrieved=extractFiles (JDL::INPUTSB, isb, extracted,
								lookInto_b,wmpURI,isbURI,extractedAd.get()) || toBretrieved;
							// put the extracted files back into the InputSandbox attribute
							for(;iter_i<extracted.size();iter_i++){	// Iterate ONLY over new value(s)
								val.SetStringValue(extracted[iter_i]);	// create classad Value
								isVect.push_back(Literal::MakeLiteral(val));	// Update ISB value
							}
							break;
						case Value::UNDEFINED_VALUE:
							// It's an Expression evaluated
							inputRemotes.push_back( vectList[i]->Copy() );
							isVect.push_back(vectList[i]->Copy());
							break;
						default:
							throw AdMismatchException (__FILE__,__LINE__,
							METHOD,WMS_JDLMISMATCH , JDL::INPUTSB );
					}
				}else{
					// It's an Expression not evaluated, leave it unchanged
					inputRemotes.push_back( vectList[i]->Copy() );
					isVect.push_back(vectList[i]->Copy());
				}
				val.Clear() ;
			}
		}
		break;
		default:
			throw AdMismatchException (__FILE__ , __LINE__ ,METHOD, WMS_JDLMISMATCH , JDL::INPUTSB );
			break;
	}
	classad:ExprTree* tmp_expr = ExprList::MakeExprList(isVect);
	Insert (JDL::INPUTSB , tmp_expr) ;
	GLITE_STACK_JDL_CATCH_ALL() ; //Exiting from method: remove line from stack trace
}
예제 #10
0
int
ClassAdLog::ExamineTransaction(const char *key, const char *name, char *&val, ClassAd* &ad)
{
	bool AdDeleted=false, ValDeleted=false, ValFound=false;
	int attrsAdded = 0;

	if (!active_transaction) return 0;

	for (LogRecord *log = active_transaction->FirstEntry(key); log; 
		 log = active_transaction->NextEntry()) {

		switch (log->get_op_type()) {
		case CondorLogOp_NewClassAd: {
			if (AdDeleted) {	// check to see if ad is created after a delete
				AdDeleted = false;
			}
			break;
		}
		case CondorLogOp_DestroyClassAd: {
			AdDeleted = true;
			if ( ad ) {
				delete ad;
				ad = NULL;
				attrsAdded = 0;
			}
			break;
		}
		case CondorLogOp_SetAttribute: {
			char const *lname = ((LogSetAttribute *)log)->get_name();
			if (name && strcasecmp(lname, name) == 0) {
				if (ValFound) {
					free(val);
				}
				val = strdup(((LogSetAttribute *)log)->get_value());
				ValFound = true;
				ValDeleted = false;
			}
			if (!name) {
				if ( !ad ) {
					ad = new ClassAd;
					ASSERT(ad);
				}
				if (val) {
					free(val);
					val = NULL;
				}
                ExprTree* expr = ((LogSetAttribute *)log)->get_expr();
                if (expr) {
		    expr = expr->Copy();
                    ad->Insert(lname, expr, false);
                } else {
                    val = strdup(((LogSetAttribute *)log)->get_value());
                    ad->AssignExpr(lname, val);
                }
				attrsAdded++;
			}
			break;
		}
		case CondorLogOp_DeleteAttribute: {
			char const *lname = ((LogDeleteAttribute *)log)->get_name();
			if (name && strcasecmp(lname, name) == 0) {
				if (ValFound) {
					free(val);
				}
				ValFound = false;
				ValDeleted = true;
			}
			if (!name) {
				if (ad) {
					ad->Delete(lname);
					attrsAdded--;
				}
			}
			break;
		}
		default:
			break;
		}
	}

	if ( name ) {
		if (AdDeleted || ValDeleted) return -1;
		if (ValFound) return 1;
		return 0;
	} else {
		if (attrsAdded < 0 ) {
			return 0;
		}
		return attrsAdded;
	}
}
bool operator==(const ExprTree &tree1, const ExprTree &tree2)
{
    return tree1.SameAs(&tree2);
}
예제 #12
0
bool AttributeReference::
_Flatten( EvalState &state, Value &val, ExprTree*&ntree, int*) const
{
	ExprTree	*tree;
	ExprTree	*dummy;
	const ClassAd *curAd;
	bool		rval;

	ntree = NULL; // Just to be safe...  wenger 2003-12-11.

		// find the expression and the evalstate
	curAd = state.curAd;
	switch( FindExpr( state, tree, dummy, false ) ) {
		case EVAL_FAIL:
			return false;

		case EVAL_ERROR:
			val.SetErrorValue();
			state.curAd = curAd;
			return true;

		case EVAL_UNDEF:
			if( expr && state.flattenAndInline ) {
				ExprTree *expr_ntree = NULL;
				Value expr_val;
				if( state.depth_remaining <= 0 ) {
					val.SetErrorValue();
					state.curAd = curAd;
					return false;
				}
				state.depth_remaining--;

				rval = expr->Flatten(state,expr_val,expr_ntree);

				state.depth_remaining++;

				if( rval && expr_ntree ) {
					ntree = MakeAttributeReference(expr_ntree,attributeStr);
					if( ntree ) {
						state.curAd = curAd;
						return true;
					}
				}
				delete expr_ntree;
			}
			if( !(ntree = Copy( ) ) ) {
				CondorErrno = ERR_MEM_ALLOC_FAILED;
				CondorErrMsg = "";
				state.curAd = curAd;
				return( false );
			}
			state.curAd = curAd;
			return true;

		case EVAL_OK:
		{
			// Don't flatten or inline a classad that's referred to
			// by an attribute.
			if ( tree->GetKind() == CLASSAD_NODE ) {
				ntree = Copy( );
				val.SetUndefinedValue( );
				return true;
			}

			if( state.depth_remaining <= 0 ) {
				val.SetErrorValue();
				state.curAd = curAd;
				return false;
			}
			state.depth_remaining--;

			rval = tree->Flatten( state, val, ntree );

			state.depth_remaining++;

			// don't inline if it didn't flatten to a value, and clear cache
			// do inline if FlattenAndInline was called
			if( ntree ) {
				if( state.flattenAndInline ) {	// NAC
					return true;   				// NAC
				}								// NAC
				delete ntree;
				ntree = Copy( );
				val.SetUndefinedValue( );
			}

			state.curAd = curAd;
			return rval;
		}
		default:  CLASSAD_EXCEPT( "ClassAd:  Should not reach here" );
	}
	return false;
}
예제 #13
0
void find_attribute_if(std::vector<std::string>* v, ExprTree* e, Predicate predicate, bool deep_find = false)
{
  expression_trace_type exprTrace, exprStack;

  if (!e) return;
  else exprStack.push_back(e);

  while (!exprStack.empty()) {

    exprTrace.push_front( (e = exprStack.front()) );
    exprStack.pop_front();
    
    switch( e->GetKind() ) {
    case ExprTree::LITERAL_NODE: break;
    case ExprTree::OP_NODE: 
      {
	ExprTree* e1 = 0, *e2 = 0, *e3 = 0;
	Operation::OpKind ok;
	dynamic_cast<Operation*>(e)->GetComponents(ok, e1, e2, e3);
	if ( e3 ) exprStack.push_front(e3);
	if ( e2 ) exprStack.push_front(e2);
	if ( e1 ) exprStack.push_front(e1);
      }
      break;
    case ExprTree::FN_CALL_NODE: 
      {
	std::vector<ExprTree*> args;
	std::string fn;
	dynamic_cast<FunctionCall*>(e)->GetComponents(fn, args);
	for( int i = args.size(); i; i--) exprStack.push_front( args[i-1] );
      }
      break;
    case ExprTree::EXPR_LIST_NODE: 
      {
	std::vector<ExprTree*> args;
	dynamic_cast<ExprList*>(e)->GetComponents(args);
	for( int i = args.size(); i; i--) exprStack.push_front( args[i-1] );
      }	
      break;
    case ExprTree::ATTRREF_NODE: 
      {
	AttributeReference* a = dynamic_cast<AttributeReference*>(e);
	ExprTree* reference_expr = 0;
	std::string name;
	bool absolute;
	bool continue_find = false;
	a->GetComponents(reference_expr, name, absolute);

	const ClassAd*  parent_scope   = 0;
	parent_scope=a->GetParentScope();

	if (!reference_expr) { // simple reference "attr" and ".attr"...
	  // ...look-up the parent scope to solve the reference...
	  reference_expr = parent_scope->Lookup(name);
	  if(reference_expr) continue_find = true;
	  else if(predicate(std::make_pair(&exprTrace,a)) &&
			  find(v->begin(), v->end(), name) == v->end()) {
		          
		  v->push_back(name);
	  }
	  
	}
 	else if (parent_scope && deep_find) {
	  
	  // ...reference_expr is not a simple reference "expr.attr" 
 	  // and the deep resolution is requested.
	  std::string    reference_name;
	  Value          reference_value;
	  const ClassAd* reference_ad;
	  ExprTree*      expr;
	  dynamic_cast<AttributeReference*>(reference_expr)->
	    GetComponents(expr, reference_name, absolute);
	  
	  if (parent_scope->EvaluateAttr(reference_name, reference_value) &&
	      reference_value.IsClassAdValue(reference_ad)) {
	    
	    reference_expr=reference_ad->Lookup(name);
	    continue_find = expr && !(expr->GetKind()==ExprTree::LITERAL_NODE);
	    if(!continue_find && predicate(std::make_pair(&exprTrace,a)) &&
			                              find(v->begin(), v->end(), name) == v->end()) {

		                      v->push_back(name);
		}			      
	  }
	}
	
 	// ...if the referenced expression has not been evaluated yet...
	if (reference_expr &&
	    find(exprTrace.begin(), exprTrace.end(), reference_expr) == exprTrace.end()) {
	  
	  if (continue_find) exprStack.push_front(reference_expr); // ...further search needed.
	  else if (predicate(std::make_pair(&exprTrace,a)) &&
		   find(v->begin(), v->end(), name) == v->end()) {
	    v->push_back(name);
	  } 
	}
      }
      break;
    default:
      assert( false );
    }
  }
}
예제 #14
0
// download the files associated with the jobads to the sandbox at td_sinful
// with the supplied capability.
// The work_ad should contain:
//	ATTR_TREQ_CAPABILITY
//	ATTR_TREQ_FTP
//	ATTR_TREQ_JOBID_ALLOW_LIST
bool 
DCTransferD::download_job_files(ClassAd *work_ad, CondorError * errstack)
{
	ReliSock *rsock = NULL;
	int timeout = 60 * 60 * 8; // transfers take a long time...
	int i;
	ClassAd reqad, respad;
	std::string cap;
	int ftp;
	int invalid;
	int protocol;
	std::string reason;
	int num_transfers;
	ClassAd jad;
	const char *lhstr = NULL;
	ExprTree *tree = NULL;

	//////////////////////////////////////////////////////////////////////////
	// Connect to the transferd and authenticate
	//////////////////////////////////////////////////////////////////////////

	// This call with automatically connect to _addr, which was set in the
	// constructor of this object to be the transferd in question.
	rsock = (ReliSock*)startCommand(TRANSFERD_READ_FILES, Stream::reli_sock,
		timeout, errstack);
	if( ! rsock ) {
		dprintf( D_ALWAYS, "DCTransferD::download_job_files: "
				 "Failed to send command (TRANSFERD_READ_FILES) "
				 "to the schedd\n" );
		errstack->push("DC_TRANSFERD", 1, 
			"Failed to start a TRANSFERD_READ_FILES command.");
		return false;
	}

		// First, if we're not already authenticated, force that now. 
	if (!forceAuthentication( rsock, errstack )) {
		dprintf( D_ALWAYS, "DCTransferD::download_job_files() authentication "
				"failure: %s\n", errstack->getFullText().c_str() );
		errstack->push("DC_TRANSFERD", 1, 
			"Failed to authenticate properly.");
		return false;
	}

	rsock->encode();

	//////////////////////////////////////////////////////////////////////////
	// Query the transferd about the capability/protocol and see if I can 
	// download my files. It will respond with a classad saying good or bad.
	//////////////////////////////////////////////////////////////////////////

	work_ad->LookupString(ATTR_TREQ_CAPABILITY, cap);
	work_ad->LookupInteger(ATTR_TREQ_FTP, ftp);

	reqad.Assign(ATTR_TREQ_CAPABILITY, cap);
	reqad.Assign(ATTR_TREQ_FTP, ftp);

	// This request ad to the transferd should contain:
	//	ATTR_TREQ_CAPABILITY
	//	ATTR_TREQ_FTP
	reqad.put(*rsock);
	rsock->end_of_message();

	rsock->decode();

	// This response ad from the transferd should contain:
	// ATTR_TREQ_INVALID_REQUEST (set to true)
	// ATTR_TREQ_INVALID_REASON
	//
	// OR
	//
	//	ATTR_TREQ_INVALID_REQUEST (set to false)
	//	ATTR_TREQ_NUM_TRANSFERS
	//
	respad.initFromStream(*rsock);
	rsock->end_of_message();

	respad.LookupInteger(ATTR_TREQ_INVALID_REQUEST, invalid);
	
	if (invalid == TRUE) {
		// The transferd rejected my attempt to upload the fileset
		delete rsock;
		respad.LookupString(ATTR_TREQ_INVALID_REASON, reason);
		errstack->push("DC_TRANSFERD", 1, reason.c_str());
		return false;
	}

	respad.LookupInteger(ATTR_TREQ_NUM_TRANSFERS, num_transfers);

	//////////////////////////////////////////////////////////////////////////
	// Based upon the protocol I've chosen, use that method to download the
	// files. When using the FileTrans protocol, a child process on the
	// transferd side will be sending me individual job ads and then 
	// instantiating a filetransfer object for that ad.
	//////////////////////////////////////////////////////////////////////////

	dprintf(D_ALWAYS, "Receiving fileset");
	work_ad->LookupInteger(ATTR_TREQ_FTP, protocol);
	switch(protocol) {
		case FTP_CFTP: // download the files using the FileTransfer Object
			for (i = 0; i < num_transfers; i++) {

				// Grab a job ad the server is sending us so we know what
				// to receive.
				jad.initFromStream(*rsock);
				rsock->end_of_message();

				// translate the job ad by replacing the 
				// saved SUBMIT_ attributes so the download goes into the
				// correct place.
				jad.ResetExpr();
				while( jad.NextExpr(lhstr, tree) ) {
					if ( lhstr && strncasecmp("SUBMIT_",lhstr,7)==0 ) {
							// this attr name starts with SUBMIT_
							// compute new lhs (strip off the SUBMIT_)
						const char *new_attr_name = strchr(lhstr,'_');
						ExprTree * pTree;
						ASSERT(new_attr_name);
						new_attr_name++;
							// insert attribute
						pTree = tree->Copy();
						jad.Insert(new_attr_name, pTree, false);
					}
				}	// while next expr
		
				// instantiate a filetransfer object and have it accept the
				// files.
				FileTransfer ftrans;
				if ( !ftrans.SimpleInit(&jad, false, false, rsock) )
				{
					delete rsock;
					errstack->push("DC_TRANSFERD", 1, 
						"Failed to initate uploading of files.");
					return false;
				}

				// We want files to be copied to their final places, so apply
				// any filename remaps when downloading.
				if ( !ftrans.InitDownloadFilenameRemaps(&jad) ) {
					return false;
				}

				ftrans.setPeerVersion( version() );

				if ( !ftrans.DownloadFiles() ) {
					delete rsock;
					errstack->push("DC_TRANSFERD", 1, 
						"Failed to download files.");
					return false;
				}

				dprintf(D_ALWAYS | D_NOHEADER, ".");
			}	
			rsock->end_of_message();

			dprintf(D_ALWAYS | D_NOHEADER, "\n");

			break;

		default:
			// Bail due to user error. This client doesn't support the unknown
			// protocol.

			delete rsock;
			errstack->push("DC_TRANSFERD", 1, 
				"Unknown file transfer protocol selected.");
			return false;
			break;
	}

	//////////////////////////////////////////////////////////////////////////
	// Get the response from the transferd once it sees a completed 
	// movement of files to the child process.
	//////////////////////////////////////////////////////////////////////////

	rsock->decode();
	respad.initFromStream(*rsock);
	rsock->end_of_message();

	// close up shop
	delete rsock;

	respad.LookupInteger(ATTR_TREQ_INVALID_REQUEST, invalid);
	if ( invalid == TRUE ) {
		respad.LookupString(ATTR_TREQ_INVALID_REASON, reason);
		errstack->push("DC_TRANSFERD", 1, reason.c_str());
		return false;
	}

	return true;
}
예제 #15
0
파일: statsd.cpp 프로젝트: valtri/htcondor
bool
Metric::evaluate(char const *attr_name,classad::Value &result,classad::ClassAd &metric_ad,classad::ClassAd const &daemon_ad,MetricTypeEnum type,ExtArray<MyString> *regex_groups,char const *regex_attr)
{
	bool retval = true;
	ExprTree *expr = NULL;
	if( !(expr=metric_ad.Lookup(attr_name)) ) {
		return true;
	}
	classad::ClassAd const *ad = &daemon_ad;
	ClassAd daemon_ad_copy;
	if( regex_attr ) {
		// make a modifiable copy of daemon_ad and insert regex_attr = regex_attr, so the user-defined expression can refer to it
		daemon_ad_copy = daemon_ad;
		ad = &daemon_ad_copy;
		daemon_ad_copy.AssignExpr(ATTR_REGEX,regex_attr);
	}
	expr->SetParentScope(ad);
	if( !ad->EvaluateExpr(expr,result) ||
		(type == STRING && !result.IsStringValue()) ||
		(type == DOUBLE && !result.IsNumber()) ||
        (type == FLOAT && !result.IsNumber()) ||
        (type == INT8 && !result.IsIntegerValue()) ||
        (type == UINT8 && !result.IsIntegerValue()) ||
        (type == INT16 && !result.IsIntegerValue()) ||
        (type == UINT16 && !result.IsIntegerValue()) ||
        (type == INT32 && !result.IsIntegerValue()) ||
        (type == UINT32 && !result.IsIntegerValue()) ||
		(type == BOOLEAN && !result.IsBooleanValue()) )
	{
		retval = false;
		classad::ClassAdUnParser unparser;
		std::string expr_str;
		unparser.Unparse(expr_str,expr);
		dprintf(D_FULLDEBUG,"Failed to evaluate the following%s%s: %s=%s\n",
				name.empty() ? "" : " attribute of metric ",
				name.c_str(),
				attr_name,
				expr_str.c_str());
	}
	expr->SetParentScope(&metric_ad);

	// do regex macro substitutions
	if( regex_groups && regex_groups->length() > 0 ) {
		std::string str_value;
		if( result.IsStringValue(str_value) && str_value.find("\\")!=std::string::npos ) {
			std::string new_str_value;
			const char *ch = str_value.c_str();
			while( *ch ) {
				if( *ch == '\\' ) {
					ch++;
					if( !isdigit(*ch) ) {
						new_str_value += *(ch++);
					}
					else {
						char *endptr = NULL;
						long index = strtol(ch,&endptr,10);
						ch = endptr;
						if( index < regex_groups->length() ) {
							new_str_value += (*regex_groups)[index];
						}
					}
				}
				else {
					new_str_value += *(ch++);
				}
			}
			result.SetStringValue(new_str_value);
		}
	}

	return retval;
}
예제 #16
0
void BaseJob::JobAdUpdateFromSchedd( const ClassAd *new_ad, bool full_ad )
{
    static const char *held_removed_update_attrs[] = {
        ATTR_JOB_STATUS,
        ATTR_HOLD_REASON,
        ATTR_HOLD_REASON_CODE,
        ATTR_HOLD_REASON_SUBCODE,
        ATTR_LAST_HOLD_REASON,
        ATTR_RELEASE_REASON,
        ATTR_LAST_RELEASE_REASON,
        ATTR_ENTERED_CURRENT_STATUS,
        ATTR_NUM_SYSTEM_HOLDS,
        ATTR_REMOVE_REASON,
        NULL
    };

    int new_condor_state;

    new_ad->LookupInteger( ATTR_JOB_STATUS, new_condor_state );

    if ( new_condor_state == condorState ) {
        if ( !full_ad ) {
            MergeClassAds( jobAd, const_cast<ClassAd*>(new_ad), true, false );
        }
        return;
    }

    if ( new_condor_state == REMOVED && condorState == HELD ) {
        int release_status = IDLE;
        jobAd->LookupInteger( ATTR_JOB_STATUS_ON_RELEASE, release_status );
        if ( release_status == REMOVED ) {
            // We already know about this REMOVED state and have
            // decided to go on hold afterwards, so ignore this
            // "update".
            return;
        }
    }

    if ( new_condor_state == REMOVED || new_condor_state == HELD ) {

        for ( int i = 0; held_removed_update_attrs[i] != NULL; i++ ) {
            ExprTree *expr;

            if ( (expr = new_ad->LookupExpr( held_removed_update_attrs[i] )) != NULL ) {
                ExprTree * pTree = expr->Copy();
                jobAd->Insert( held_removed_update_attrs[i], pTree, false );
            } else {
                jobAd->Delete( held_removed_update_attrs[i] );
            }
            jobAd->SetDirtyFlag( held_removed_update_attrs[i], false );
        }

        if ( new_condor_state == HELD && writeUserLog && !holdLogged ) {
            // TODO should this log event be delayed until gridmanager is
            //   done dealing with the job?
            WriteHoldEventToUserLog( jobAd );
            holdLogged = true;
        }

        // If we're about to put a job on hold and learn that it's been
        // removed, make sure the state returns to removed when it is
        // released. This is normally checked in JobHeld(), but it's
        // possible to learn of the removal just as we're about to
        // update the schedd with the hold.
        if ( new_condor_state == REMOVED && condorState == HELD ) {
            bool dirty;
            jobAd->GetDirtyFlag( ATTR_JOB_STATUS, NULL, &dirty );
            if ( dirty ) {
                jobAd->Assign( ATTR_JOB_STATUS_ON_RELEASE, REMOVED );
            }
        }

        condorState = new_condor_state;
        // TODO do we need to call UpdateRuntimeStats() here?
        UpdateRuntimeStats();
        SetEvaluateState();

    } else if ( new_condor_state == COMPLETED ) {

        condorState = new_condor_state;
        // TODO do we need to update any other attributes?
        SetEvaluateState();
    } else if ( !full_ad ) {
        MergeClassAds( jobAd, const_cast<ClassAd*>(new_ad), true, false );
    }

}
예제 #17
0
/*********************************************************************
 *
 * Function: process_evaluate
 * Purpose:  Given a line that begins with "evaluate", parse the rest
 *           of the line and perform the evaluation.
 *
 *********************************************************************/
static void process_evaluate(const string &line,
							 int token_start, int line_number, 
							 const Parameters &parameters,
							 ErrorCount *errors)
{
	string classad_name, expression_string;
	ExprTree       *expr;
	ClassAdParser  parser;

	classad_name = extract_token(&token_start, line);
	expr = NULL;
	if ((unsigned) token_start < line.size()) {
		expression_string = line.substr(token_start, line.size() - token_start);
	} else {
		expression_string = "";
	}
	if (!classad_name.compare("") 
		|| !expression_string.compare("")) {
		cout << "Error: Missing evaluate information on line " << line_number 
			 << "." << endl;
		cout << "       Format: evaluate <classad> <expression>"
			 << endl;
		errors->IncrementErrors();
	}
	else {
		if (!parser.ParseExpression(expression_string, expr)) {
			cout << "Error: Can't parse expression (" << expression_string 
				 << ") on line " << line_number << "." << endl;
			errors->IncrementErrors();
		}
		else {
			ClassAd *classad = classads[classad_name];
			
			if (classad == NULL) {
				cout << "Error: Unknown ClassAd: \"" << classad_name 
					 << "\" on line " << line_number << "." << endl;
				errors->IncrementErrors();
			}
			else {
				Value  value;
				expr->SetParentScope(classad);
				if (!classad->EvaluateExpr(expr, value)) {
					cout << "Error: Can't evaluate expression (" << expression_string 
						 << ") on line " <<line_number << "." << endl;
					errors->IncrementErrors();
				}
				else {
					PrettyPrint unparser;
					string value_string;

					unparser.Unparse(value_string, value);
					cout << "OK: Evaluating \"" << expression_string
						 << "\" in " << classad_name 
						 << " evaluates to " << value_string
						 << " on line " << line_number << endl;
				}
			}
		}
	}
	if (expr != NULL) {
		delete expr;
	}
	return;
}
예제 #18
0
bool 
DCSchedd::receiveJobSandbox(const char* constraint, CondorError * errstack, int * numdone /*=0*/)
{
	if(numdone) { *numdone = 0; }
	ExprTree *tree = NULL;
	const char *lhstr;
	int reply;
	int i;
	ReliSock rsock;
	int JobAdsArrayLen;
	bool use_new_command = true;

	if ( version() ) {
		CondorVersionInfo vi( version() );
		if ( vi.built_since_version(6,7,7) ) {
			use_new_command = true;
		} else {
			use_new_command = false;
		}
	}

		// // // // // // // //
		// On the wire protocol
		// // // // // // // //

	rsock.timeout(20);   // years of research... :)
	if( ! rsock.connect(_addr) ) {
		dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: "
				 "Failed to connect to schedd (%s)\n", _addr );
		return false;
	}
	if ( use_new_command ) {
		if( ! startCommand(TRANSFER_DATA_WITH_PERMS, (Sock*)&rsock, 0,
						   errstack) ) {
			dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: "
					 "Failed to send command (TRANSFER_DATA_WITH_PERMS) "
					 "to the schedd\n" );
			return false;
		}
	} else {
		if( ! startCommand(TRANSFER_DATA, (Sock*)&rsock, 0, errstack) ) {
			dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: "
					 "Failed to send command (TRANSFER_DATA) "
					 "to the schedd\n" );
			return false;
		}
	}

		// First, if we're not already authenticated, force that now. 
	if (!forceAuthentication( &rsock, errstack )) {
		dprintf( D_ALWAYS, 
			"DCSchedd::receiveJobSandbox: authentication failure: %s\n",
			errstack ? errstack->getFullText().c_str() : "" );
		return false;
	}

	rsock.encode();

		// Send our version if using the new command
	if ( use_new_command ) {
			// Need to use a named variable, else the wrong version of	
			// code() is called.
		char *my_version = strdup( CondorVersion() );
		if ( !rsock.code(my_version) ) {
			dprintf(D_ALWAYS,"DCSchedd:receiveJobSandbox: "
					"Can't send version string to the schedd\n");
			free( my_version );
			return false;
		}
		free( my_version );
	}

		// Send the constraint
	char * nc_constraint = strdup( constraint );	// de-const
	if ( !rsock.code(nc_constraint) ) {
		free( nc_constraint );
		dprintf(D_ALWAYS,"DCSchedd:receiveJobSandbox: "
				"Can't send JobAdsArrayLen to the schedd\n");
		return false;
	}
	free( nc_constraint );

	if ( !rsock.end_of_message() ) {
		std::string errmsg;
		formatstr(errmsg,
				"Can't send initial message (version + constraint) to schedd (%s)",
				_addr);

		dprintf(D_ALWAYS,"DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str());

		if( errstack ) {
			errstack->push(
				"DCSchedd::receiveJobSandbox",
				CEDAR_ERR_EOM_FAILED,
				errmsg.c_str());
		}
		return false;
	}

		// Now, read how many jobs matched the constraint.
	rsock.decode();
	if ( !rsock.code(JobAdsArrayLen) ) {
		std::string errmsg;
		formatstr(errmsg,
				"Can't receive JobAdsArrayLen from the schedd (%s)",
				_addr);

		dprintf(D_ALWAYS,"DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str());

		if( errstack ) {
			errstack->push(
				"DCSchedd::receiveJobSandbox",
				CEDAR_ERR_GET_FAILED,
				errmsg.c_str());
		}
		return false;
	}

	rsock.end_of_message();

	dprintf(D_FULLDEBUG,"DCSchedd:receiveJobSandbox: "
		"%d jobs matched my constraint (%s)\n",
		JobAdsArrayLen, constraint);

		// Now read all the files via the file transfer object
	for (i=0; i<JobAdsArrayLen; i++) {
		FileTransfer ftrans;
		ClassAd job;

			// grab job ClassAd
		if ( !getClassAd(&rsock, job) ) {
			std::string errmsg;
			formatstr(errmsg, "Can't receive job ad %d from the schedd", i);

			dprintf(D_ALWAYS, "DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str());

			if( errstack ) {
				errstack->push(
							   "DCSchedd::receiveJobSandbox",
							   CEDAR_ERR_GET_FAILED,
							   errmsg.c_str());
			}
			return false;
		}

		rsock.end_of_message();

			// translate the job ad by replacing the 
			// saved SUBMIT_ attributes
		job.ResetExpr();
		while( job.NextExpr(lhstr, tree) ) {
			if ( lhstr && strncasecmp("SUBMIT_",lhstr,7)==0 ) {
					// this attr name starts with SUBMIT_
					// compute new lhs (strip off the SUBMIT_)
				const char *new_attr_name = strchr(lhstr,'_');
				ExprTree * pTree;
				ASSERT(new_attr_name);
				new_attr_name++;
					// insert attribute
				pTree = tree->Copy();
				job.Insert(new_attr_name, pTree, false);
			}
		}	// while next expr

		if ( !ftrans.SimpleInit(&job,false,false,&rsock) ) {
			if( errstack ) {
				int cluster = -1, proc = -1;
				job.LookupInteger(ATTR_CLUSTER_ID,cluster);
				job.LookupInteger(ATTR_PROC_ID,proc);
				errstack->pushf(
					"DCSchedd::receiveJobSandbox",
					FILETRANSFER_INIT_FAILED,
					"File transfer initialization failed for target job %d.%d",
					cluster, proc );
			}
			return false;
		}
		// We want files to be copied to their final places, so apply
		// any filename remaps when downloading.
		if ( !ftrans.InitDownloadFilenameRemaps(&job) ) {
			return false;
		}
		if ( use_new_command ) {
			ftrans.setPeerVersion( version() );
		}
		if ( !ftrans.DownloadFiles() ) {
			if( errstack ) {
				FileTransfer::FileTransferInfo ft_info = ftrans.GetInfo();

				int cluster = -1, proc = -1;
				job.LookupInteger(ATTR_CLUSTER_ID,cluster);
				job.LookupInteger(ATTR_PROC_ID,proc);
				errstack->pushf(
					"DCSchedd::receiveJobSandbox",
					FILETRANSFER_DOWNLOAD_FAILED,
					"File transfer failed for target job %d.%d: %s",
					cluster, proc, ft_info.error_desc.Value() );
			}
			return false;
		}
	}	
		
	rsock.end_of_message();

	rsock.encode();

	reply = OK;
	rsock.code(reply);
	rsock.end_of_message();

	if(numdone) { *numdone = JobAdsArrayLen; }

	return true;
}
예제 #19
0
void
VMUniverseMgr::publish( ClassAd* ad, amask_t  /*mask*/ )
{
	if( !ad ) {
		return;
	}
	if( !m_starter_has_vmcode || ( m_vm_type.Length() == 0 )) {
		ad->Assign(ATTR_HAS_VM, false);
		return;
	}

	ad->Assign(ATTR_HAS_VM, true);

	// publish the number of still executable Virtual machines
	if( m_vm_max_num > 0 ) {
		int avail_vm_num = m_vm_max_num - numOfRunningVM();
		ad->Assign(ATTR_VM_AVAIL_NUM, avail_vm_num);
	}else {
		// no limit of the number of executable VM
		ad->Assign(ATTR_VM_AVAIL_NUM, VM_AVAIL_UNLIMITED_NUM);
	}

	// we will publish all information provided by vmgahp server
	m_vmgahp_info.ResetExpr();

	ExprTree* expr = NULL;
	const char *attr_name = NULL;
	while(m_vmgahp_info.NextExpr(attr_name, expr)) {
		// we need to adjust available vm memory
		if( strcasecmp(attr_name, ATTR_VM_MEMORY) == MATCH ) {
			int freemem = getFreeVMMemSize();
			ad->Assign(ATTR_VM_MEMORY, freemem);
		}else if( strcasecmp(attr_name, ATTR_VM_NETWORKING) == MATCH ) {
			ad->Assign(ATTR_VM_NETWORKING, m_vm_networking); 
		}else {
			ExprTree * pTree =  expr->Copy();
			ad->Insert(attr_name, pTree, false);
		}
	}

	// Now, we will publish mac and ip addresses of all guest VMs.
	MyString all_macs;
	MyString all_ips;
	VMStarterInfo *info = NULL;
	const char* guest_ip = NULL;
	const char* guest_mac = NULL;

	m_vm_starter_list.Rewind();
	while( m_vm_starter_list.Next(info) ) {
		guest_ip = info->getIPForVM();
		if( guest_ip ) {
			if( all_ips.IsEmpty() == false ) {
				all_ips += ",";
			}
			all_ips += guest_ip;
		}

		guest_mac = info->getMACForVM();
		if( guest_mac ) {
			if( all_macs.IsEmpty() == false ) {
				all_macs += ",";
			}
			all_macs += guest_mac;
		}
	}
	if( all_ips.IsEmpty() == false ) {
		ad->Assign(ATTR_VM_ALL_GUEST_IPS, all_ips);
	}
	if( all_macs.IsEmpty() == false ) {
		ad->Assign(ATTR_VM_ALL_GUEST_MACS, all_macs);
	}
}
예제 #20
0
  int
  unwind_attributes(classad_context cad, char *attribute_name, char ***results) 
   {
    if (cad == NULL) return C_CLASSAD_INVALID_CONTEXT;
    if ((results == NULL) || (attribute_name == NULL))
      return C_CLASSAD_INVALID_ARG;

    ClassAd *ad = (ClassAd *)cad;

    ExprTree *et;
    bool need_to_delete_et = false;

    et = ad->Lookup(attribute_name);
    if (et == NULL)
     {
      return C_CLASSAD_VALUE_NOT_FOUND;
     }

    if (et->GetKind() == ExprTree::LITERAL_NODE)
     {
      // The attribute was probably stringified. Try to parse it.
      Value v;
      EvalState state;
      state.SetScopes( ad );

      et->Evaluate(state,v);
      std::string strres;

      if (v.IsStringValue( strres ))
       {
        ClassAdParser parser;
        et=NULL;
        parser.ParseExpression(strres,et);
        need_to_delete_et = true;
       }
     }

    BinaryOpUnwind res_unp; 
    std::string result;
    res_unp.Unparse(result, et);
    int n_results;
    if (*results == NULL)
     {
      n_results = 0;
      (*results) = (char **)malloc(sizeof(char **));
      if ((*results) == NULL) return C_CLASSAD_OUT_OF_MEMORY;
      (*results)[0] = NULL;
     }
    else
     {
      for (n_results = 0; (*results)[n_results] != NULL; n_results++) /*NOP*/ ;
     }

    std::vector<std::string>::const_iterator it;
    for (it = res_unp.m_unwind_output.begin(); 
         it != res_unp.m_unwind_output.end(); ++it)
     {
      n_results++;
      char **new_results;
      new_results = (char **)realloc(*results, (n_results+1)*sizeof(char *));
      if (new_results == NULL)
       {
        if (need_to_delete_et) delete et;
        return C_CLASSAD_OUT_OF_MEMORY;
       }
      (*results) = new_results;
      (*results)[n_results] = NULL;
      (*results)[n_results-1] = strdup(it->c_str());
      if (((*results)[n_results-1]) == NULL)
       {
        if (need_to_delete_et) delete et;
        return C_CLASSAD_OUT_OF_MEMORY;
       }
     }

    if (need_to_delete_et) delete et;
    return C_CLASSAD_NO_ERROR;
   }
예제 #21
0
파일: Job.cpp 프로젝트: blueskyll/condor
void
LiveJobImpl::Set ( const char *_name, const char *_value )
{

    if ( strcasecmp ( _name, ATTR_JOB_SUBMISSION ) == 0 )
    {
        std::string val = TrimQuotes( _value );
        // TODO: grab the cluster from our key
        PROC_ID id = getProcByString(m_job->GetKey());
        if (m_job) {
            m_job->SetSubmission ( val.c_str(), id.cluster );
        }
    }

    // our status is changing...decrement for old one
    if ( strcasecmp ( _name, ATTR_JOB_STATUS ) == 0 )
    {
        if ( m_job )
        {
            m_job->SetStatus(this->GetStatus());
            m_job->DecrementSubmission ();
        }
    }

    if ( strcasecmp ( _name, ATTR_OWNER ) == 0 )
    {
        // need to leave an owner for this job
        // to be picked up soon
        // if we are in here, we don't have m_submission
        PROC_ID id = getProcByString(m_job->GetKey());
        std::string val = TrimQuotes( _value );
        g_ownerless_clusters[id.cluster] = val;
        m_job->UpdateSubmission(id.cluster,val.c_str());
    }

    // parse the type
    ExprTree *expr;
    if ( ParseClassAdRvalExpr ( _value, expr ) )
    {
        dprintf ( D_ALWAYS,
                  "error: parsing %s[%s] = %s, skipping\n",
                  m_job->GetKey(), _name, _value );
        return;
    }
    // add this value to the classad
    classad::Value value;
    expr->Evaluate(value);
    switch ( value.GetType() )
    {
    case classad::Value::INTEGER_VALUE:
        int i;
        from_string<int> ( i, std::string ( _value ), std::dec );
        m_full_ad->Assign ( _name, i );
        break;
    case classad::Value::REAL_VALUE:
        float f;
        from_string<float> ( f, std::string ( _value ), std::dec );
        m_full_ad->Assign ( _name, f );
        break;
    case classad::Value::STRING_VALUE:
        m_full_ad->Assign ( _name, _value );
        break;
    default:
        m_full_ad->AssignExpr ( _name, _value );
        break;
    }
    delete expr;
    expr = NULL;

    // our status has changed...increment for new one
    if ( strcasecmp ( _name, ATTR_JOB_STATUS ) == 0 )
    {
        if ( m_job )
        {
            m_job->SetStatus(this->GetStatus());
            m_job->IncrementSubmission ();
        }
    }
}