예제 #1
0
void test_user_policy_periodic_exit_yes(void)
{
	int val;
	int action;
	char buf[4096];
	ClassAd *result;
	ClassAd *jad = new ClassAd;
	if (jad == NULL)
	{
		printf("Out of memory!\n");
		exit(EXIT_FAILURE);
	}
	
	printf("=========================================\n");
	printf("Testing User Policy on Periodic Exit: YES\n");

	/* set up the classad */
	sprintf(buf, "%s = 42", ATTR_TOTAL_SUSPENSIONS);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_PERIODIC_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = TotalSuspensions == 42", ATTR_PERIODIC_REMOVE_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_ON_EXIT_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK);
	jad->Insert(buf);
	jad->Assign(ATTR_JOB_STATUS, RUNNING);

	result = user_job_policy(jad);

	result->EvalBool(ATTR_USER_POLICY_ERROR, result, val);
	if(val == true)
	{
		printf("An error happened\n");
		delete result;
		return;
	}

	result->EvalBool(ATTR_TAKE_ACTION, result, val);
	if (val == true)
	{
		printf("%s was true.\n", ATTR_TAKE_ACTION);
		result->LookupInteger(ATTR_USER_POLICY_ACTION, action);
		printf("Action is: %s\n", 
			action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB":
			"UNKNOWN");
		result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf);
		printf("Reason for action: %s\n", buf);
	}
	else
	{
		printf("Something went wrong. I should have had an action to take.\n");
	}
}
예제 #2
0
void test_user_policy_periodic_hold_no(void)
{
	int val;
	char buf[4096];
	ClassAd *result;
	ClassAd *jad = new ClassAd;
	if (jad == NULL)
	{
		printf("Out of memory!\n");
		exit(EXIT_FAILURE);
	}
	
	printf("========================================\n");
	printf("Testing User Policy on Periodic Hold: NO\n");

	/* set up the classad */
	sprintf(buf, "%s = 40", ATTR_TOTAL_SUSPENSIONS);
	jad->Insert(buf);
	sprintf(buf, "%s = TotalSuspensions == 42", ATTR_PERIODIC_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_PERIODIC_REMOVE_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_ON_EXIT_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK);
	jad->Insert(buf);
	jad->Assign(ATTR_JOB_STATUS, RUNNING);

	result = user_job_policy(jad);

	result->EvalBool(ATTR_USER_POLICY_ERROR, result, val);
	if(val == true)
	{
		printf("An error happened\n");
		delete result;
		return;
	}

	result->EvalBool(ATTR_TAKE_ACTION, result, val);
	if (val == true)
	{
		printf("Something went wrong. I should not have had an action.\n");
	}
	else
	{
		printf("Ignoring correctly.\n");
	}
}
예제 #3
0
int
LogSetAttribute::Play(void *data_structure)
{
	ClassAdHashTable *table = (ClassAdHashTable *)data_structure;
	int rval;
	ClassAd *ad = 0;
	if (table->lookup(HashKey(key), ad) < 0)
		return -1;
    if (value_expr) {
		// Such a shame, do we really need to make a
		// copy of value_expr here?  Seems like we could just
		// assign it and then set value_expr to NULL and avoid
		// copying a parse tree, since after we Play it I doubt
		// this class does anything more with value_expr beyond
		// deallocating it.  - Todd 11/13 <*****@*****.**>
        ExprTree * pTree = value_expr->Copy();
        rval = ad->Insert(name, pTree, false);
    } else {
        rval = ad->AssignExpr(name, value);
    }
	ad->SetDirtyFlag(name, is_dirty);

#if defined(HAVE_DLOPEN)
	ClassAdLogPluginManager::SetAttribute(key, name, value);
#endif

	return rval;
}
예제 #4
0
// convert list of expressions into a classad
//
static void printJobIfConstraint(std::vector<std::string> & exprs, const char* constraint, ExprTree *constraintExpr)
{
	if ( ! exprs.size())
		return;

	ClassAd ad;
	size_t ix;

	// convert lines vector into classad.
	while ((ix = exprs.size()) > 0) {
		const char * pexpr = exprs[ix-1].c_str();
		if ( ! ad.Insert(pexpr)) {
			dprintf(D_ALWAYS,"failed to create classad; bad expr = '%s'\n", pexpr);
			printf( "\t*** Warning: Bad history file; skipping malformed ad(s)\n" );
			exprs.clear();
			return;
		}
		exprs.pop_back();
	}

	if (!constraint || constraint[0]=='\0' || EvalBool(&ad, constraintExpr)) {
		printJob(ad);
		matchCount++; // if control reached here, match has occured
	}
}
예제 #5
0
  int
  classad_put_string_list_attribute (classad_context *cad, 
                                     const char *name, 
                                     char **value)
   {
    if (value == NULL) return C_CLASSAD_INVALID_VALUE;

    ClassAd *ad;
    if ((*cad) == NULL) 
     {
      ad = new ClassAd;
      (*cad) = (classad_context) ad;
     }
    else ad = (ClassAd *)(*cad);

    char **str_val;

    std::vector<ExprTree*> et_ads;

    // Traverse NULL-terminated string array.
    for(str_val=value; (*str_val) != NULL; str_val++) 
     {
      Value v;
      v.SetStringValue(*str_val);
      et_ads.push_back(Literal::MakeLiteral(v));
     }

    ExprList *et_value;
    et_value = ExprList::MakeExprList(et_ads);

    if (ad->Insert (name, et_value)) return C_CLASSAD_NO_ERROR; 
    else                             return C_CLASSAD_INSERT_FAILED;
   }
예제 #6
0
파일: view.cpp 프로젝트: AlainRoy/htcondor
bool View::
SetConstraintExpr( ClassAdCollection *coll, ExprTree *constraint )
{
	ClassAd					*ad;
	ViewMembers::iterator	vmi;
	bool					match;
	string					key;

		// insert expression into ad in left context
	if( !( ad=evalEnviron.GetLeftAd() ) ||
		!ad->Insert( ATTR_REQUIREMENTS, constraint ) ) {
		CondorErrMsg += "; failed to set constraint on view";
		return( false );
	}

		// check if all members still belong to the view
	for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) {
		vmi->GetKey( key );
		if( ( ad = coll->GetClassAd( key ) ) == NULL ) {
			CLASSAD_EXCEPT( "internal error: classad in view but not in collection" );
		}
		evalEnviron.ReplaceRightAd( ad );
		match = evalEnviron.EvaluateAttrBool("RightMatchesLeft",match) && match;
		evalEnviron.RemoveRightAd( );
			// if classad doesn't match constraint remove from view
		if( !match ) {
			ClassAdDeleted( coll, key, ad );
		}
	}

	return( true );
}
예제 #7
0
파일: view.cpp 프로젝트: AlainRoy/htcondor
View::
View( View *parentView )
{
	Value				val;
	vector<ExprTree*>	vec;

	ClassAd	*ad = evalEnviron.GetLeftAd( );
	parent = parentView;
	ExprTree* pExp;
	ad->InsertAttr( ATTR_REQUIREMENTS, true );
	ad->Insert( ATTR_RANK, (pExp=Literal::MakeLiteral( val )) );
	ad->Insert( ATTR_PARTITION_EXPRS, (pExp=ExprList::MakeExprList( vec )) );
	if( parentView ) {
		ad->InsertAttr( "ParentViewName", parentView->GetViewName( ) );
	}
}
예제 #8
0
static void set_usageAd (ClassAd* jobAd, ClassAd ** ppusageAd) 
{
	std::string resslist;
	if ( ! jobAd->LookupString("ProvisionedResources", resslist))
		resslist = "Cpus, Disk, Memory";

	StringList reslist(resslist.c_str());
	if (reslist.number() > 0) {
		ClassAd * puAd = new ClassAd();
		puAd->Clear(); // get rid of default "CurrentTime = time()" value.

		reslist.rewind();
		while (const char * resname = reslist.next()) {
			std::string attr;
			std::string res = resname;
			title_case(res); // capitalize it to make it print pretty.
			const int copy_ok = classad::Value::ERROR_VALUE | classad::Value::BOOLEAN_VALUE | classad::Value::INTEGER_VALUE | classad::Value::REAL_VALUE;
			classad::Value value;
			attr = res + "Provisioned";	 // provisioned value
			if (jobAd->EvalAttr(attr.c_str(), NULL, value) && (value.GetType() & copy_ok) != 0) {
				classad::ExprTree * plit = classad::Literal::MakeLiteral(value);
				if (plit) {
					puAd->Insert(resname, plit); // usage ad has attribs like they appear in Machine ad
				}
			}
			// /*for debugging*/ else { puAd->Assign(resname, 42); }
			attr = "Request"; attr += res;   	// requested value
			if (jobAd->EvalAttr(attr.c_str(), NULL, value)&& (value.GetType() & copy_ok) != 0) {
				classad::ExprTree * plit = classad::Literal::MakeLiteral(value);
				if (plit) {
					puAd->Insert(attr.c_str(), plit);
				}
			}
			// /*for debugging*/ else { puAd->Assign(attr.Value(), 99); }
			attr = res + "Usage"; // usage value
			if (jobAd->EvalAttr(attr.c_str(), NULL, value) && (value.GetType() & copy_ok) != 0) {
				classad::ExprTree * plit = classad::Literal::MakeLiteral(value);
				if (plit) {
					puAd->Insert(attr.c_str(), plit);
				}
			}
		}
		*ppusageAd = puAd;
	}
}
예제 #9
0
Starter*
StarterMgr::makeStarter( const char* path )
{
	Starter* new_starter;
	FILE* fp;
	char *args[] = { const_cast<char*>(path),
					 const_cast<char*>("-classad"),
					 NULL };
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
		// note we run the starter here as root if possible,
		// since that is how the starter will be invoked for real,
		// and the real uid of the starter may influence the
		// list of capabilities the "-classad" option returns.
	{
		TemporaryPrivSentry sentry(PRIV_ROOT);
		fp = my_popenv( args, "r", FALSE );
	}

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid starter\n", buf );
			delete( ad );
			pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, 
				 "\"%s -classad\" did not produce any output, ignoring\n", 
				 path ); 
		delete( ad );
		return NULL;
	}

	new_starter = new Starter();
	new_starter->setAd( ad );
	new_starter->setPath( path );
	int is_dc = 0;
	ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc );
	new_starter->setIsDC( (bool)is_dc );

	return new_starter;
}
예제 #10
0
Starter*
StarterMgr::makeStarter( const char* path )
{
	Starter* new_starter;
	FILE* fp;
	char *args[] = { const_cast<char*>(path),
					 const_cast<char*>("-classad"),
					 NULL };
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
	fp = my_popenv( args, "r", FALSE );

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid starter\n", buf );
			delete( ad );
			pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, 
				 "\"%s -classad\" did not produce any output, ignoring\n", 
				 path ); 
		delete( ad );
		return NULL;
	}

	new_starter = new Starter();
	new_starter->setAd( ad );
	new_starter->setPath( path );
	int is_dc = 0;
	ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc );
	new_starter->setIsDC( (bool)is_dc );

	return new_starter;
}
예제 #11
0
파일: view.cpp 프로젝트: AlainRoy/htcondor
bool View::
SetRankExpr( ClassAdCollection *coll, ExprTree *rank )
{
	ClassAd					*ad;
	ViewMember				vm;
	MemberIndex::iterator	mIdxItr;
	ViewMembers::iterator	vmi;
	string					key;
	Value					rankValue;

		// insert expression into ad in left context
	if( !( ad=evalEnviron.GetLeftAd() ) ) {
		CLASSAD_EXCEPT( "internal error:  view has no view info" );
	}
	
	if( !ad->Insert( ATTR_RANK, rank ) ) {
		CondorErrMsg += "failed to set rank on view";
		return( false );
	}

		// clear out member list
	viewMembers.clear( );

		// re-order content by new rank expression
	for( mIdxItr=memberIndex.begin(); mIdxItr!=memberIndex.end(); mIdxItr++ ) {
		key = mIdxItr->first;
		if( ( ad = coll->GetClassAd( key ) ) == NULL	||
			!evalEnviron.ReplaceRightAd( ad )			||
			!evalEnviron.EvaluateAttr( "LeftRankValue", rankValue ) ) {
				// internal error
			CLASSAD_EXCEPT( "internal error:  could not determine 'Rank' value" );
		}

			// insert into member list
		vm.SetKey( key );
		vm.SetRankValue( rankValue );
		viewMembers.insert( vm );
	}

		// now re-do the index
	memberIndex.clear( );
	for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) {
		vmi->GetKey( key );
		memberIndex[key] = vmi;
	}

	return( true );
}
예제 #12
0
void test_oldstyle_with_exit(void)
{
	int val;
	int action;
	char buf[4096];
	ClassAd *result;
	ClassAd *jad = new ClassAd;
	if (jad == NULL)
	{
		printf("Out of memory!\n");
		exit(EXIT_FAILURE);
	}
	
	printf("==================================================\n");
	printf("Testing OldStyle job where it is marked as exited.\n");

	/* An oldstyle classad would have this */
	sprintf(buf, "%s = %d", ATTR_COMPLETION_DATE, 10); /* non zero */
	jad->Insert(buf);

	result = user_job_policy(jad);

	result->EvalBool(ATTR_USER_POLICY_ERROR, result, val);
	if(val == true)
	{
		printf("An error happened\n");
		delete result;
		return;
	}

	result->EvalBool(ATTR_TAKE_ACTION, result, val);
	if (val == true)
	{
		printf("%s was true.\n", ATTR_TAKE_ACTION);
		result->LookupInteger(ATTR_USER_POLICY_ACTION, action);
		printf("Action is: %s\n", 
			action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB":
			"UNKNOWN");
		result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf);
		printf("Reason for action: %s\n", buf);
	}
	else
	{
		printf("Something went wrong. I should have had an action to take.\n");
	}
}
예제 #13
0
ClassAd *ClassAdCollectionInterface::
_ModifyClassAd( const string &xactionName, const string &key, ClassAd *ad )
{
    ClassAd *rec;
    if( !( rec = new ClassAd( ) ) ) {
        CondorErrno = ERR_MEM_ALLOC_FAILED;
        CondorErrMsg = "";
        return( (ClassAd*) NULL );
    }
    if( ( !xactionName.empty( ) && 
			!rec->InsertAttr( ATTR_XACTION_NAME, xactionName ) )	||
            !rec->InsertAttr( "OpType",ClassAdCollOp_ModifyClassAd )||
            !rec->InsertAttr( "Key", key )                 			||
            !rec->Insert( "Ad", ad ) ) {
        CondorErrMsg += "; failed to make modify classad " + key + " record";
        delete rec;
        return( (ClassAd*) NULL );
    }
    return( rec );
}
예제 #14
0
void test_oldstyle_with_no_exit(void)
{
	int val;
	char buf[4096];
	ClassAd *result;
	ClassAd *jad = new ClassAd;
	if (jad == NULL)
	{
		printf("Out of memory!\n");
		exit(EXIT_FAILURE);
	}
	
	printf("======================================================\n");
	printf("Testing OldStyle job where it is NOT marked as exited.\n");

	/* An oldstyle classad would have this */
	sprintf(buf, "%s = %d", ATTR_COMPLETION_DATE, 0);
	jad->Insert(buf);

	result = user_job_policy(jad);

	result->EvalBool(ATTR_USER_POLICY_ERROR, result, val);
	if(val == true)
	{
		printf("An error happened\n");
		delete result;
		return;
	}

	result->EvalBool(ATTR_TAKE_ACTION, result, val);
	if (val == true)
	{
		printf("Something went wrong. I should not have had an action.\n");
	}
	else
	{
		printf("Ignoring correctly.\n");
	}

	delete result;
}
예제 #15
0
int
LogSetAttribute::Play(void *data_structure)
{
	ClassAdHashTable *table = (ClassAdHashTable *)data_structure;
	int rval;
	ClassAd *ad = 0;
	if (table->lookup(HashKey(key), ad) < 0)
		return -1;
    if (value_expr) {
        ExprTree * pTree = value_expr->Copy();
        rval = ad->Insert(name, pTree, false);
    } else {
        rval = ad->AssignExpr(name, value);
    }
	ad->SetDirtyFlag(name, is_dirty);

#if defined(HAVE_DLOPEN)
	ClassAdLogPluginManager::SetAttribute(key, name, value);
#endif

	return rval;
}
예제 #16
0
Shadow*
ShadowMgr::makeShadow( const char* path )
{
	Shadow* new_shadow;
	FILE* fp;
	const char *args[] = {const_cast<char*>(path), "-classad", NULL};
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
	fp = my_popenv( args, "r", FALSE );

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid shadow\n", buf );
			delete( ad );
			my_pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, "\"%s -classad\" did not produce any output, "
				 "ignoring\n", path ); 
		delete( ad );
		return NULL;
	}
	new_shadow = new Shadow( path, ad );
	return new_shadow;
}
예제 #17
0
ClassAd *ClassAdXMLParser::
ParseClassAd(ClassAd *classad_in)
{
	bool             in_classad;
	ClassAd          *classad = NULL;
	ClassAd          *local_ad = NULL;
	XMLLexer::Token  token;

	classad = NULL;
	in_classad = false;

	while (lexer.PeekToken(&token)) {
		if (!in_classad) {
			lexer.ConsumeToken(NULL);
			if (   token.token_type == XMLLexer::tokenType_Tag 
				&& token.tag_id     == XMLLexer::tagID_ClassAd) {
				
				// We have a ClassAd tag
				if (token.tag_type   == XMLLexer::tagType_Start) {
					in_classad = true;
					if ( classad_in ) {
						classad_in->Clear();
						classad = classad_in;
					} else {
						local_ad = new ClassAd();
						classad = local_ad;
					}
					classad->DisableDirtyTracking();
				} else {
					// We're done, return the ClassAd we got, if any.
                    in_classad = false;
					break;
				}
			}
		} else {
			if (token.token_type == XMLLexer::tokenType_Tag) {
			  if (token.tag_id   == XMLLexer::tagID_Attribute) {
			    if (token.tag_type == XMLLexer::tagType_Invalid) {
				  delete local_ad;
			      return NULL;
			    } else if( token.tag_type == XMLLexer::tagType_Start) {
					string attribute_name;
					ExprTree *tree;
					
					tree = ParseAttribute(attribute_name);
					if (tree != NULL) {
						classad->Insert(attribute_name, tree);
					}
					else {
					  delete local_ad;
					  return NULL;
					}
			    } else {
					lexer.ConsumeToken(NULL);
				}
              } else if (token.tag_id   == XMLLexer::tagID_ClassAd) {
                  lexer.ConsumeToken(NULL);
                  if (token.tag_type == XMLLexer::tagType_End) {
                      in_classad = false;
                      break;
                  } else {
                      // This is invalid, but we'll just ignore it.
                  }
			  } else if (   token.tag_id != XMLLexer::tagID_XML
							  && token.tag_id != XMLLexer::tagID_XMLStylesheet
							  && token.tag_id != XMLLexer::tagID_Doctype
							  && token.tag_id != XMLLexer::tagID_ClassAds) {
					// We got a non-attribute, non-xml thingy within a 
					// ClassAd. That must be an error, but we'll just skip
					// it in the hopes of recovering.
					lexer.ConsumeToken(NULL);
					break;
				}
			} else {
				lexer.ConsumeToken(NULL);
			}
		}
	}
	if (classad != NULL) {
		classad->EnableDirtyTracking();
	}
	return classad;
}
예제 #18
0
ClassAd*
readJobAd( void )
{
    ClassAd* ad = NULL;
    bool is_stdin = false;
    bool read_something = false;

    ASSERT( job_ad_file );

    if( job_ad_file[0] == '-' && job_ad_file[1] == '\0' ) {
        fp = stdin;
        is_stdin = true;
    } else {
        if (fp == NULL) {
            fp = safe_fopen_wrapper_follow( job_ad_file, "r" );
            if( ! fp ) {
                EXCEPT( "Failed to open ClassAd file (%s): %s (errno %d)",
                        job_ad_file, strerror(errno), errno );
            }
        }
    }

    dprintf( D_FULLDEBUG, "Reading job ClassAd from %s\n",
             is_stdin ? "STDIN" : job_ad_file );

    ad = new ClassAd;
    MyString line;
    while( line.readLine(fp) ) {
        read_something = true;
        line.chomp();
        if( line[0] == '#' ) {
            dprintf( D_JOB, "IGNORING COMMENT: %s\n", line.Value() );
            continue;
        }
        if( line == "***" ) {
            dprintf( D_JOB, "Saw ClassAd delimitor, stopping\n" );
            break;
        }
        if( ! ad->Insert(line.Value()) ) {
            EXCEPT( "Failed to insert \"%s\" into ClassAd!", line.Value() );
        }
    }
    if( ! read_something ) {
        EXCEPT( "reading ClassAd from (%s): file is empty",
                is_stdin ? "STDIN" : job_ad_file );
    }
    if( IsDebugVerbose(D_JOB) ) {
        ad->dPrint( D_JOB );
    }

    // For debugging, see if there's a special attribute in the
    // job ad that sends us into an infinite loop, waiting for
    // someone to attach with a debugger
    int shadow_should_wait = 0;
    ad->LookupInteger( ATTR_SHADOW_WAIT_FOR_DEBUG,
                       shadow_should_wait );
    if( shadow_should_wait ) {
        dprintf( D_ALWAYS, "Job requested shadow should wait for "
                 "debugger with %s=%d, going into infinite loop\n",
                 ATTR_SHADOW_WAIT_FOR_DEBUG, shadow_should_wait );
        while( shadow_should_wait ) { }
    }

    return ad;
}
void
XferSummary::time_out(time_t now, char *hostaddr)
{
	ClassAd	   	info;
	char		line[128], *tmp;
	char		*str = NULL;

	info.SetMyTypeName("CkptServer");
	info.SetTargetTypeName("CkptFile");

	sprintf(line, "%s = \"%s\"", ATTR_NAME, my_full_hostname() );
	info.Insert(line);
    sprintf(line, "%s = \"%s\"", ATTR_MACHINE, hostaddr );
	info.Insert(line);
	sprintf(line, "%s = \"%s\"", ATTR_VERSION, CondorVersion() );
	info.Insert(line);
	sprintf(line, "%s = \"%s\"", ATTR_PLATFORM, CondorPlatform() );
	info.Insert(line);
	sprintf(line, "NumSends = %d", num_sends);
	info.Insert(line);
	sprintf(line, "BytesSent = %d", (int) bytes_sent);
	info.Insert(line);
	sprintf(line, "TimeSending = %d", time_sending);
	info.Insert(line);
	sprintf(line, "AvgSendBandwidth = %f", num_sends ?
			tot_send_bandwidth / num_sends : 0.0);
	info.Insert(line);
	sprintf(line, "NumRecvs = %d", num_recvs);
	info.Insert(line);
	sprintf(line, "BytesReceived = %d", (int) bytes_recv);
	info.Insert(line);
	sprintf(line, "TimeReceiving = %d", time_recving);
	info.Insert(line);
	sprintf(line, "AvgReceiveBandwidth = %f", num_recvs ?
			tot_recv_bandwidth / num_recvs : 0.0);
	info.Insert(line);

	/* ctime adds a newline at the end of the ascii conversion.... */
	str = ctime(&start_time);
	sprintf(line, "CkptServerIntervalStart = \"%s\"", str ? str : "Unknown\n");
	tmp = strchr( line, '\n' );
	if (tmp != NULL) {
		/* delete the newline */
		*tmp = '\"';
		tmp++;
		*tmp = '\0';
	}
	info.Insert(line);

	/* ctime adds a newline at the end of the ascii conversion.... */
	str = ctime(&now);
	sprintf(line, "CkptServerIntervalEnd = \"%s\"", str ? str : "Unknown\n");
	tmp = strchr( line, '\n' );
	if (tmp != NULL) {
		/* delete the newline */
		*tmp = '\"';
		tmp++;
		*tmp = '\0';
	}
	info.Insert(line);

	sprintf(line, "Disk = %d", sysapi_disk_space(pwd.Value()) );
	info.Insert(line);
	
	// Send to collector
	if ( Collectors ) {
        dprintf(D_NETWORK, "Sending CkptServer ClassAd:\n");
        info.dPrint(D_NETWORK);
		Collectors->sendUpdates (UPDATE_CKPT_SRVR_AD, &info, NULL, true);
	}

	init();
}
예제 #20
0
파일: view.cpp 프로젝트: AlainRoy/htcondor
bool View::
DeletePartitionedView( ClassAdCollection *coll, const ViewName &vName )
{
	PartitionedViews::iterator 	mi;

	for( mi = partitionedViews.begin( ); mi != partitionedViews.end( ); mi++ ) {
		if( mi->second->GetViewName( ) == vName ) {
				// check if the partition is non-empty ...
			if( mi->second->Size( ) != 0 ) {
					// remove all child views and reset view info
				View						*view = mi->second;
				SubordinateViews::iterator	svi;
				PartitionedViews::iterator	pvi;

					// delete subordinate views
				for( svi = view->subordinateViews.begin( ); 
						svi != view->subordinateViews.end( ); svi++ ) {
					(*svi)->DeleteView( coll );
					delete (*svi);
				}
				view->subordinateViews.clear( );

					// delete partitioned views
				for( pvi = view->partitionedViews.begin( ); 
						pvi != view->partitionedViews.end( ); pvi++ ) {
					pvi->second->DeleteView( coll );
					delete pvi->second;
				}
				view->partitionedViews.clear( );

					// reset name of view
				coll->UnregisterView( vName );
				coll->RegisterView( viewName + ":" + mi->first, view );

					// reset other view info
				vector<ExprTree*> vec;
				ExprTree * pExpr=0;
				ClassAd *ad = new ClassAd( );
				if( !ad ) {
					CondorErrno = ERR_MEM_ALLOC_FAILED;
					CondorErrMsg = "";
					return( false );
				}
				if( !ad->InsertAttr( ATTR_REQUIREMENTS, true )	||
						!ad->InsertAttr( ATTR_RANK, 0 )				||
						!ad->Insert(ATTR_PARTITION_EXPRS,
							(pExpr=ExprList::MakeExprList( vec )) )	||
						!view->SetViewInfo( coll, ad ) ) {
					CondorErrMsg += "; failed to delete partition view " +
						vName;
					return( false );
				}
				return( true );
			}

				// empty partition ... can just delete it
			mi->second->DeleteView( coll );
			delete mi->second;
			partitionedViews.erase( mi );
			return( true );
		}
	}
	CondorErrno = ERR_NO_SUCH_VIEW;
	CondorErrMsg = "no partition child view named " + vName + " in view";
	return( false );
}
예제 #21
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;
}
예제 #22
0
ClassAd *CollectorEngine::
collect (int command,ClassAd *clientAd,const condor_sockaddr& from,int &insert,Sock *sock)
{
	ClassAd		*retVal;
	ClassAd		*pvtAd;
	int		insPvt;
	AdNameHashKey		hk;
	HashString	hashString;
	static int repeatStartdAds = -1;		// for debugging
	ClassAd		*clientAdToRepeat = NULL;
	_condor_auto_accum_runtime<collector_runtime_probe> rt(CollectorEngine_rucc_runtime);
	double rt_last = rt.begin;

	if (repeatStartdAds == -1) {
		repeatStartdAds = param_integer("COLLECTOR_REPEAT_STARTD_ADS",0);
	}

	if( !ValidateClassAd(command,clientAd,sock) ) {
		return NULL;
	}

	CollectorEngine_rucc_validateAd_runtime.Add(rt.tick(rt_last));

	// mux on command
	switch (command)
	{
	  case UPDATE_STARTD_AD:
	  case UPDATE_STARTD_AD_WITH_ACK:
		if ( repeatStartdAds > 0 ) {
			clientAdToRepeat = new ClassAd(*clientAd);
		}
		if (!makeStartdAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );

		CollectorEngine_rucc_makeHashKey_runtime.Add(rt.tick(rt_last));

		retVal=updateClassAd (StartdAds, "StartdAd     ", "Start",
							  clientAd, hk, hashString, insert, from );

		if (last_updateClassAd_was_insert) { CollectorEngine_rucc_insertAd_runtime.Add(rt.tick(rt_last));
		} else { CollectorEngine_rucc_updateAd_runtime.Add(rt.tick(rt_last)); }

		// if we want to store private ads
		if (!sock)
		{
			dprintf (D_ALWAYS, "Want private ads, but no socket given!\n");
			break;
		}
		else
		{
			if (!(pvtAd = new ClassAd))
			{
				EXCEPT ("Memory error!");
			}
			if( !getClassAd(sock, *pvtAd) )
			{
				dprintf(D_FULLDEBUG,"\t(Could not get startd's private ad)\n");
				delete pvtAd;
				break;
			}

				// Fix up some stuff in the private ad that we depend on.
				// We started doing this in 7.2.0, so once we no longer
				// care about compatibility with stuff from before then,
				// the startd could stop bothering to send these attributes.

				// Queries of private ads depend on the following:
			SetMyTypeName( *pvtAd, STARTD_ADTYPE );

				// Negotiator matches up private ad with public ad by
				// using the following.
			if( retVal ) {
				CopyAttribute( ATTR_MY_ADDRESS, *pvtAd, *retVal );
				CopyAttribute( ATTR_NAME, *pvtAd, *retVal );
			}

			CollectorEngine_rucc_getPvtAd_runtime.Add(rt.tick(rt_last));

			// insert the private ad into its hashtable --- use the same
			// hash key as the public ad
			(void) updateClassAd (StartdPrivateAds, "StartdPvtAd  ",
								  "StartdPvt", pvtAd, hk, hashString, insPvt,
								  from );
			if (last_updateClassAd_was_insert) { CollectorEngine_rucc_insertPvtAd_runtime.Add(rt.tick(rt_last));
			} else { CollectorEngine_rucc_updatePvtAd_runtime.Add(rt.tick(rt_last)); }
		}

		// create fake duplicates of this ad, each with a different name, if
		// we are told to do so.  this feature exists for developer
		// scalability testing.
		if ( repeatStartdAds > 0 && clientAdToRepeat ) {
			ClassAd *fakeAd;
			int n;
			char newname[150],oldname[130];
			oldname[0] = '\0';
			clientAdToRepeat->LookupString("Name",oldname,sizeof(oldname));
			for (n=0;n<repeatStartdAds;n++) {
				fakeAd = new ClassAd(*clientAdToRepeat);
				snprintf(newname,sizeof(newname),
						 "Name=\"fake%d-%s\"",n,oldname);
				fakeAd->Insert(newname);
				makeStartdAdHashKey (hk, fakeAd);
				hashString.Build( hk );
				if (! updateClassAd (StartdAds, "StartdAd     ", "Start",
							  fakeAd, hk, hashString, insert, from ) )
				{
					// don't leak memory if there is some failure
					delete fakeAd;
				}
			}
			delete clientAdToRepeat;
			clientAdToRepeat = NULL;
			CollectorEngine_rucc_repeatAd_runtime.Add(rt.tick(rt_last));
		}
		break;

	  case MERGE_STARTD_AD:
		if (!makeStartdAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=mergeClassAd (StartdAds, "StartdAd     ", "Start",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_SCHEDD_AD:
		if (!makeScheddAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (ScheddAds, "ScheddAd     ", "Schedd",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_SUBMITTOR_AD:
		// use the same hashkey function as a schedd ad
		if (!makeScheddAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		// since submittor ads always follow a schedd ad, and a master check is
		// performed for schedd ads, we don't need a master check in here
		hashString.Build( hk );
		retVal=updateClassAd (SubmittorAds, "SubmittorAd  ", "Submittor",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_LICENSE_AD:
		// use the same hashkey function as a schedd ad
		if (!makeLicenseAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		// since submittor ads always follow a schedd ad, and a master check is
		// performed for schedd ads, we don't need a master check in here
		hashString.Build( hk );
		retVal=updateClassAd (LicenseAds, "LicenseAd  ", "License",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_MASTER_AD:
		if (!makeMasterAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (MasterAds, "MasterAd     ", "Master",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_CKPT_SRVR_AD:
		if (!makeCkptSrvrAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (CkptServerAds, "CkptSrvrAd   ", "CkptSrvr",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_COLLECTOR_AD:
		if (!makeCollectorAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (CollectorAds, "CollectorAd  ", "Collector",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_STORAGE_AD:
		if (!makeStorageAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (StorageAds, "StorageAd  ", "Storage",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_ACCOUNTING_AD:
		if (!makeAccountingAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (AccountingAds, "AccountingAd  ", "Accouting",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_NEGOTIATOR_AD:
		if (!makeNegotiatorAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		if (m_allowOnlyOneNegotiator) {
			// first, purge all the existing negotiator ads, since we
			// want to enforce that *ONLY* 1 negotiator is in the
			// collector any given time.
			purgeHashTable( NegotiatorAds );
		}
		retVal=updateClassAd (NegotiatorAds, "NegotiatorAd  ", "Negotiator",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_HAD_AD:
		if (!makeHadAdHashKey (hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (HadAds, "HadAd  ", "HAD",
							  clientAd, hk, hashString, insert, from );
		break;

	  case UPDATE_GRID_AD:
		if (!makeGridAdHashKey(hk, clientAd))
		{
			dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			insert = -3;
			retVal = 0;
			break;
		}
		hashString.Build( hk );
		retVal=updateClassAd (GridAds, "GridAd  ", "Grid",
							  clientAd, hk, hashString, insert, from );
          break;

	  case UPDATE_AD_GENERIC:
	  {
		  const char *type_str = GetMyTypeName(*clientAd);
		  if (type_str == NULL) {
			  dprintf(D_ALWAYS, "collect: UPDATE_AD_GENERIC: ad has no type\n");
			  insert = -3;
			  retVal = 0;
			  break;
		  }
		  MyString type(type_str);
		  CollectorHashTable *cht = findOrCreateTable(type);
		  if (cht == NULL) {
			  dprintf(D_ALWAYS, "collect: findOrCreateTable failed\n");
			  insert = -3;
			  retVal = 0;
			  break;
		  }
		  if (!makeGenericAdHashKey (hk, clientAd))
		  {
			  dprintf(D_ALWAYS, "Could not make hashkey --- ignoring ad\n");
			  insert = -3;
			  retVal = 0;
			  break;
		  }
		  hashString.Build(hk);
		  retVal = updateClassAd(*cht, type_str, type_str, clientAd,
					 hk, hashString, insert, from);
		  break;
	  }

	  case QUERY_STARTD_ADS:
	  case QUERY_SCHEDD_ADS:
	  case QUERY_MASTER_ADS:
	  case QUERY_SUBMITTOR_ADS:
	  case QUERY_CKPT_SRVR_ADS:
	  case QUERY_STARTD_PVT_ADS:
	  case QUERY_COLLECTOR_ADS:
  	  case QUERY_NEGOTIATOR_ADS:
  	  case QUERY_HAD_ADS:
	  case QUERY_GENERIC_ADS:
	  case INVALIDATE_STARTD_ADS:
	  case INVALIDATE_SCHEDD_ADS:
	  case INVALIDATE_MASTER_ADS:
	  case INVALIDATE_CKPT_SRVR_ADS:
	  case INVALIDATE_SUBMITTOR_ADS:
	  case INVALIDATE_COLLECTOR_ADS:
	  case INVALIDATE_NEGOTIATOR_ADS:
	  case INVALIDATE_HAD_ADS:
	  case INVALIDATE_ADS_GENERIC:
		// these are not implemented in the engine, but we allow another
		// daemon to detect that these commands have been given
	    insert = -2;
		retVal = 0;
	    break;

	  default:
		dprintf (D_ALWAYS, "Received illegal command: %d\n", command);
		insert = -1;
		retVal = 0;
	}

	if (command != UPDATE_STARTD_AD && command != UPDATE_STARTD_AD_WITH_ACK) {
		CollectorEngine_rucc_other_runtime.Add(rt.tick(rt_last));
	}


	// return the updated ad
	return retVal;
}
예제 #23
0
/* This function determines what should be done with a job given the user
	policy specifed in the job ad. If no policy is specified, then a classad
	is returned detailing that nothing should be done because there wasn't
	a user policy. You are responsible for freeing the classad you get back
	from this function. It can be used in a periodic fashion on job ads
	and has the notion of "nothing should be done to this job" present
	in the classad result you get back. */
ClassAd* user_job_policy(ClassAd *jad)
{
	ClassAd *result;
	char buf[4096]; /* old classads needs to go away */
	int on_exit_hold = 0, on_exit_remove = 0;
	int cdate = 0;
	int adkind;
	
	if (jad == NULL)
	{
		EXCEPT( "Could not evaluate user policy due to job ad being NULL!\n" );
	}

	/* Set up the default response of do nothing. The caller should
		just check for this attribute and ATTR_USER_POLICY_ERROR and
		do nothing to the rest of the classad of ATTR_TAKE_ACTION
		is false. */
	result = new ClassAd;
	if (result == NULL)
	{
		EXCEPT("Out of memory!"); /* XXX should this be here? */
	}
	sprintf(buf, "%s = FALSE", ATTR_TAKE_ACTION);
	result->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_USER_POLICY_ERROR);
	result->Insert(buf);

	/* figure out the ad kind and then do something with it */

	adkind = JadKind(jad);

	switch(adkind)
	{
		case USER_ERROR_NOT_JOB_AD:
			dprintf(D_ALWAYS, "user_job_policy(): I have something that "
					"doesn't appear to be a job ad! Ignoring.\n");

			sprintf(buf, "%s = TRUE", ATTR_USER_POLICY_ERROR);
			result->Insert(buf);
			sprintf(buf, "%s = %u", ATTR_USER_ERROR_REASON, 
				USER_ERROR_NOT_JOB_AD);
			result->Insert(buf);

			return result;
			break;

		case USER_ERROR_INCONSISTANT:
			dprintf(D_ALWAYS, "user_job_policy(): Inconsistant jobad state "
								"with respect to user_policy. Detail "
								"follows:\n");
			{
				ExprTree *ph_expr = jad->LookupExpr(ATTR_PERIODIC_HOLD_CHECK);
				ExprTree *pr_expr = jad->LookupExpr(ATTR_PERIODIC_REMOVE_CHECK);
				ExprTree *pl_expr = jad->LookupExpr(ATTR_PERIODIC_RELEASE_CHECK);
				ExprTree *oeh_expr = jad->LookupExpr(ATTR_ON_EXIT_HOLD_CHECK);
				ExprTree *oer_expr = jad->LookupExpr(ATTR_ON_EXIT_REMOVE_CHECK);

				EmitExpression(D_ALWAYS, ATTR_PERIODIC_HOLD_CHECK, ph_expr);
				EmitExpression(D_ALWAYS, ATTR_PERIODIC_REMOVE_CHECK, pr_expr);
				EmitExpression(D_ALWAYS, ATTR_PERIODIC_RELEASE_CHECK, pl_expr);
				EmitExpression(D_ALWAYS, ATTR_ON_EXIT_HOLD_CHECK, oeh_expr);
				EmitExpression(D_ALWAYS, ATTR_ON_EXIT_REMOVE_CHECK, oer_expr);
			}

			sprintf(buf, "%s = TRUE", ATTR_USER_POLICY_ERROR);
			result->Insert(buf);
			sprintf(buf, "%s = %u", ATTR_USER_ERROR_REASON, 
				USER_ERROR_INCONSISTANT);
			result->Insert(buf);

			return result;
			break;

		case KIND_OLDSTYLE:
			jad->LookupInteger(ATTR_COMPLETION_DATE, cdate);
			if (cdate > 0)
			{
				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					old_style_exit);
				result->Insert(buf);
			}
			return result;
			break;

		case KIND_NEWSTYLE:
		{
			/*	The user_policy is checked in this
				order. The first one to succeed is the winner:
		
				periodic_hold
				periodic_exit
				on_exit_hold
				on_exit_remove
			*/

			UserPolicy userpolicy;
			userpolicy.Init(jad);
			int analyze_result = userpolicy.AnalyzePolicy(PERIODIC_ONLY);

			/* should I perform a periodic hold? */
			if(analyze_result == HOLD_IN_QUEUE)
			{
				/* make a result classad explaining this and return it */

				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, HOLD_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					userpolicy.FiringExpression());
				result->Insert(buf);

				return result;
			}

			/* Should I perform a periodic remove? */
			if(analyze_result == REMOVE_FROM_QUEUE)
			{
				/* make a result classad explaining this and return it */

				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					userpolicy.FiringExpression());
				result->Insert(buf);

				return result;
			}

			/* Should I perform a periodic release? */
			if(analyze_result == RELEASE_FROM_HOLD)
			{
				/* make a result classad explaining this and return it */

				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					userpolicy.FiringExpression());
				result->Insert(buf);

				return result;
			}

			/* Check to see if ExitSignal or ExitCode 
				are defined, if not, then assume the
				job hadn't exited and don't check the
				policy. This could hide a mistake of
				the caller to insert those attributes
				correctly but allows checking of the
				job ad in a periodic context. */
			if (jad->LookupExpr(ATTR_ON_EXIT_CODE) == 0 && 
				jad->LookupExpr(ATTR_ON_EXIT_SIGNAL) == 0)
			{
				return result;
			}

			/* Should I hold on exit? */
			jad->EvalBool(ATTR_ON_EXIT_HOLD_CHECK, jad, on_exit_hold);
			if (on_exit_hold == 1)
			{
				/* make a result classad explaining this and return it */

				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, HOLD_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					ATTR_ON_EXIT_HOLD_CHECK);
				result->Insert(buf);

				return result;
			}

			/* Should I remove on exit? */
			jad->EvalBool(ATTR_ON_EXIT_REMOVE_CHECK, jad, on_exit_remove);
			if (on_exit_remove == 1)
			{
				/* make a result classad explaining this and return it */

				sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION);
				result->Insert(buf);
				sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB);
				result->Insert(buf);
				sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, 
					ATTR_ON_EXIT_REMOVE_CHECK);
				result->Insert(buf);

				return result;
			}

			/* just return the default of leaving the job in idle state */
			return result;

			break;
		}

		default:
			dprintf(D_ALWAYS, "JadKind() returned unknown ad kind\n");

			/* just return the default of leaving the job in idle state. This
				is safest. */
			return result;

			break;
	}

	/* just return the default of leaving the job in idle state */
	return result;
}
예제 #24
0
ClassAd * ProcAd::dumpToAd( piPTR pi ) {

  char line[128];
  ClassAd *ad = new ClassAd;

  SetMyTypeName( *ad, "PROCESS_INFORMATION" );
  SetTargetTypeName( *ad, "ENQUIRING_MINDS_WANT_TO_KNOW" );

  sprintf ( line, "THIS_PID = %d", pi->pid );
  ad->Insert(line);
  sprintf ( line, "PARENT_PID = %ld", (long)pi->ppid );
  ad->Insert(line);
  sprintf ( line, "IMAGE_SIZE = %ld", (long)pi->imgsize );
  ad->Insert(line);
  sprintf ( line, "RESIDENT_SET_SIZE = %ld", (long)pi->rssize );
  ad->Insert(line);
#if HAVE_PSS
  if( pi->pssize_available ) {
	  sprintf ( line, "PROPORTIONAL_SET_SIZE = %ld", (long)pi->pssize );
	  ad->Insert(line);
  }
#endif
  sprintf ( line, "MAJOR_PAGE_FAULTS = %ld", (long)pi->majfault );
  ad->Insert(line);
  sprintf ( line, "MINOR_PAGE_FAULTS = %ld", (long)pi->minfault );
  ad->Insert(line);
  sprintf ( line, "USER_TIME = %ld", (long)pi->user_time );
  ad->Insert(line);
  sprintf ( line, "SYSTEM_TIME = %ld", (long)pi->sys_time );
  ad->Insert(line);
  sprintf ( line, "PROCESS_AGE = %ld", (long)pi->age );
  ad->Insert(line);
  sprintf ( line, "PERCENT_CPU_USAGE = %6.2f",  pi->cpuusage );
  ad->Insert(line);

  return ad;
}
예제 #25
0
void test_user_policy_on_exit_hold_no(void)
{
	int val;
	int action;
	char buf[4096];
	ClassAd *result;
	ClassAd *jad = new ClassAd;
	if (jad == NULL)
	{
		printf("Out of memory!\n");
		exit(EXIT_FAILURE);
	}
	
	printf("=======================================\n");
	printf("Testing User Policy on On Exit Hold: NO\n");

	/* set up the classad */
	sprintf(buf, "%s = %d", ATTR_ON_EXIT_CODE, 0);
	jad->Insert(buf);
	sprintf(buf, "%s = 40", ATTR_TOTAL_SUSPENSIONS);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_PERIODIC_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = FALSE", ATTR_PERIODIC_REMOVE_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = TotalSuspensions == 42", ATTR_ON_EXIT_HOLD_CHECK);
	jad->Insert(buf);
	sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK);
	jad->Insert(buf);

	result = user_job_policy(jad);

	result->EvalBool(ATTR_USER_POLICY_ERROR, result, val);
	if(val == true)
	{
		printf("An error happened\n");
		delete result;
		return;
	}

	result->EvalBool(ATTR_TAKE_ACTION, result, val);
	if (val == true)
	{
		printf("%s was true.\n", ATTR_TAKE_ACTION);
		result->LookupInteger(ATTR_USER_POLICY_ACTION, action);
		printf("Action is: %s\n", 
			action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB":
			"UNKNOWN");
		result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf);
		printf("Reason for action: %s\n", buf);

		if (strcmp(ATTR_USER_POLICY_FIRING_EXPR, ATTR_ON_EXIT_HOLD_CHECK) == 0)
		{
			printf("Failed. I got removed because exit_hold was true.\n");
		}
		else
		{
			printf("Success. I was removed because of %s, not because of %s\n", 
				ATTR_ON_EXIT_REMOVE_CHECK, ATTR_ON_EXIT_HOLD_CHECK);
		}
	}
	else
	{
		printf("Ignoring correctly.\n");
	}
}
예제 #26
0
void MachAttributes::init_machine_resources() {
    // defines the space of local machine resources, and their quantity
    m_machres_map.clear();

    // this may be filled from resource inventory scripts
    m_machres_attr.Clear();

    // these are reserved for standard/fixed resources
    std::set<string> fixedRes;
    fixedRes.insert("cpu");
    fixedRes.insert("cpus");
    fixedRes.insert("disk");
    fixedRes.insert("swap");
    fixedRes.insert("mem");
    fixedRes.insert("memory");
    fixedRes.insert("ram");

    // get the list of defined local resource names:
    char* ptmp = param("MACHINE_RESOURCE_NAMES");
    string resnames;
    if (NULL != ptmp) {
        // if admin defined MACHINE_RESOURCE_NAMES, then use this list
        // as the source of expected custom machine resources
        resnames = ptmp;
        free(ptmp);
    } else {
        // otherwise, build the list of custom machine resources from
        // all occurrences of MACHINE_RESOURCE_<resname>
        std::set<string> resset;
        Regex re;
        int err = 0;
        const char* pszMsg = 0;
        const string prefix = "MACHINE_RESOURCE_";
        const string invprefix = "INVENTORY_";
        const string restr = prefix + "(.+)";
        ASSERT(re.compile(restr.c_str(), &pszMsg, &err, PCRE_CASELESS));
	std::vector<std::string> resdef;
        const int n = param_names_matching(re, resdef);
        for (int j = 0;  j < n;  ++j) {
            string rname = resdef[j].substr(prefix.length());
            string testinv = rname.substr(0, invprefix.length());
            if (0 == strcasecmp(testinv.c_str(), invprefix.c_str())) {
                // if something was defined via MACHINE_RESOURCE_INVENTORY_<rname>, strip "INVENTORY_"
                rname = rname.substr(invprefix.length());
            }
            std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower);
            resset.insert(rname);
        }
        for (std::set<string>::iterator j(resset.begin());  j != resset.end();  ++j) {
            resnames += " ";
            resnames += *j;
        }
    }

    // scan the list of local resources, to obtain their quantity and associated attributes (if any)
    StringList reslist(resnames.c_str());
    reslist.rewind();
    while (const char* rnp = reslist.next()) {
        string rname(rnp);
        std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower);
        if (fixedRes.count(rname) > 0) {
            EXCEPT("pre-defined resource name '%s' is reserved", rname.c_str());
        }

        // If MACHINE_RESOURCE_<rname> is present, use that and move on:
        string pname;
        formatstr(pname, "MACHINE_RESOURCE_%s", rname.c_str());
        char* machresp = param(pname.c_str());
        if (machresp) {
            int v = param_integer(pname.c_str(), 0, 0, INT_MAX);
            m_machres_map[rname] = v;
            free(machresp);
            continue;
        }

        // current definition of REMIND macro is not working with gcc
        #pragma message("MACHINE_RESOURCE_INVENTORY_<rname> is deprecated, and will be removed when a solution using '|' in config files is fleshed out")
        // if we didn't find MACHINE_RESOURCE_<rname>, then try MACHINE_RESOURCE_INVENTORY_<rname>
        formatstr(pname, "MACHINE_RESOURCE_INVENTORY_%s", rname.c_str());
        char* invscriptp = param(pname.c_str());
        if (NULL == invscriptp) {
            EXCEPT("Missing configuration for local machine resource %s", rname.c_str());
        }

        // if there is an inventory script, then attempt to execute it and use its output to
        // identify the local resource quantity, and any associated attributes:
        string invscript = invscriptp;
        free(invscriptp);

        ArgList invcmd;
        StringList invcmdal(invscript.c_str());
        invcmdal.rewind();
        while (char* invarg = invcmdal.next()) {
            invcmd.AppendArg(invarg);
        }
        FILE* fp = my_popen(invcmd, "r", FALSE);
        if (NULL == fp) {
            EXCEPT("Failed to execute local resource inventory script \"%s\"\n", invscript.c_str());
        }

        ClassAd invad;
        char invline[1000];
        while (fgets(invline, sizeof(invline), fp)) {
            if (!invad.Insert(invline)) {
                dprintf(D_ALWAYS, "Failed to insert \"%s\" into machine resource attributes: ignoring\n", invline);
            }
        }
        my_pclose(fp);

        // require the detected machine resource to be present as an attribute
        string ccname(rname.c_str());
        *(ccname.begin()) = toupper(*(ccname.begin()));
        string detname;
        formatstr(detname, "%s%s", ATTR_DETECTED_PREFIX, ccname.c_str());
        int v = 0;
        if (!invad.LookupInteger(detname.c_str(), v)) {
            EXCEPT("Missing required attribute \"%s = <n>\" from output of %s\n", detname.c_str(),  invscript.c_str());
        }

        // success
        m_machres_map[rname] = v;
        invad.Delete(rname.c_str());
        m_machres_attr.Update(invad);
    }

    for (slotres_map_t::iterator j(m_machres_map.begin());  j != m_machres_map.end();  ++j) {
        dprintf(D_ALWAYS, "Local machine resource %s = %d\n", j->first.c_str(), int(j->second));
    }
}
예제 #27
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;
}
예제 #28
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;
}
예제 #29
0
/*! handle a log Entry: work with a job queue collection.
 *  (not with DBMS directry)
 */
QuillErrCode
JobQueueDBManager::processLogEntry(int op_type, JobQueueCollection* jobQueue)
{
	char *key, *mytype, *targettype, *name, *value;
	key = mytype = targettype = name = value = NULL;
	QuillErrCode st = QUILL_SUCCESS;

	int job_id_type;
	char cid[512];
	char pid[512];

		// REMEMBER:
		//	each get*ClassAdBody() funtion allocates the memory of 
		// 	parameters. Therefore, they all must be deallocated here,
		// and they are at the end of the routine
	switch(op_type) {
	case CondorLogOp_NewClassAd: {
		if (caLogParser->getNewClassAdBody(key, mytype, targettype) == QUILL_FAILURE)
			{
				st = QUILL_FAILURE;
				break;
			}
		job_id_type = getProcClusterIds(key, cid, pid);
		ClassAd* ad = new ClassAd();
		SetMyTypeName(*ad, "Job");
		SetTargetTypeName(*ad, "Machine");

		switch(job_id_type) {
		case IS_CLUSTER_ID:
			jobQueue->insertClusterAd(cid, ad);
			break;

		case IS_PROC_ID:
			jobQueue->insertProcAd(cid, pid, ad);
			break;

		default:
			dprintf(D_ALWAYS, "[QUILL++] New ClassAd --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}

		break;
	}
	case CondorLogOp_DestroyClassAd: {
		if (caLogParser->getDestroyClassAdBody(key) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;		
		}

		job_id_type = getProcClusterIds(key, cid, pid);

		switch(job_id_type) {
		case IS_CLUSTER_ID:
			jobQueue->removeClusterAd(cid);
			break;

		case IS_PROC_ID: {
			ClassAd *clusterad = jobQueue->find(cid);
			ClassAd *procad = jobQueue->find(cid,pid);
			if(!clusterad || !procad) {
			    dprintf(D_ALWAYS, 
						"[QUILL++] Destroy ClassAd --- Cannot find clusterad "
						"or procad in memory job queue");
				st = QUILL_FAILURE; 
				break;
			}

			jobQueue->removeProcAd(cid, pid);
			
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Destroy ClassAd --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}

		break;
	}
	case CondorLogOp_SetAttribute: {	
		if (caLogParser->getSetAttributeBody(key, name, value) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;
		}
						
		job_id_type = getProcClusterIds(key, cid, pid);

		char tmp[512];

		snprintf(tmp, 512, "%s = %s", name, value);

		switch (job_id_type) {
		case IS_CLUSTER_ID: {
			ClassAd* ad = jobQueue->findClusterAd(cid);
			if (ad != NULL) {
				ad->Insert(tmp);
			}
			else {
				dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Cluster Ad[%s]\n", cid);
			}
			break;
		}
		case IS_PROC_ID: {
			ClassAd* ad = jobQueue->findProcAd(cid, pid);
			if (ad != NULL) {
				ad->Insert(tmp);
			}
			else {
				dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Proc Ad[%s.%s]\n", cid, pid);
			}
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Set Attribute --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}
		break;
	}
	case CondorLogOp_DeleteAttribute: {
		if (caLogParser->getDeleteAttributeBody(key, name) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;
		}

		job_id_type = getProcClusterIds(key, cid, pid);

		switch(job_id_type) {
		case IS_CLUSTER_ID: {
			ClassAd* ad = jobQueue->findClusterAd(cid);
			ad->Delete(name);
			break;
		}
		case IS_PROC_ID: {
			ClassAd* ad = jobQueue->findProcAd(cid, pid);
			ad->Delete(name);
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Delete Attribute --- ERROR\n");
			st = QUILL_FAILURE; 
		}
		break;
	}
	case CondorLogOp_BeginTransaction:
		st = processBeginTransaction(true);
		break;
	case CondorLogOp_EndTransaction:
		st = processEndTransaction(true);
		break;
			// skip the log historical sequence number command
	case CondorLogOp_LogHistoricalSequenceNumber:
		break;
	default:
		printf("[QUILL++] Unsupported Job Queue Command\n");
		st = QUILL_FAILURE; 
		break;
	}

		// pointers are release
	if (key != NULL) free(key);
	if (mytype != NULL) free(mytype);
	if (targettype != NULL) free(targettype);
	if (name != NULL) free(name);
	if (value != NULL) free(value);
	return st;
}
예제 #30
0
파일: source.cpp 프로젝트: blueskyll/condor
//  ClassAd       ::= '[' AttributeList ']'
//  AttributeList ::= (epsilon)
//                  | Attribute ';' AttributeList
//  Attribute     ::= Identifier '=' Expression
bool ClassAdParser::
parseClassAd( ClassAd &ad , bool full )
{
    Lexer::TokenType 	tt;
    Lexer::TokenValue	tv;
    ExprTree			*tree = NULL;
    string				s;

    ad.Clear( );
    ad.DisableDirtyTracking();

    if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_OPEN_BOX ) return false;
    tt = lexer.PeekToken();
    while( tt != Lexer::LEX_CLOSE_BOX ) {
        // Get the name of the expression
        tt = lexer.ConsumeToken( &tv );
        if( tt == Lexer::LEX_SEMICOLON ) {
            // We allow empty expressions, so if someone give a double semicolon, it doesn't
            // hurt. Technically it's not right, but we shouldn't make users pay the price for
            // a meaningless mistake. See condor-support #1881 for a user that was bitten by this.
            continue;
        }
        if( tt != Lexer::LEX_IDENTIFIER ) {
            CondorErrno = ERR_PARSE_ERROR;
            CondorErrMsg = "while parsing classad:  expected LEX_IDENTIFIER "
                           " but got " + string( Lexer::strLexToken( tt ) );
            return false;
        }

        // consume the intermediate '='
        if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_BOUND_TO ) {
            CondorErrno = ERR_PARSE_ERROR;
            CondorErrMsg = "while parsing classad:  expected LEX_BOUND_TO "
                           " but got " + string( Lexer::strLexToken( tt ) );
            return false;
        }

        // parse the expression
        parseExpression( tree );
        if( tree == NULL ) {
            return false;
        }

        // insert the attribute into the classad
        tv.GetStringValue( s );
        if( !ad.Insert( s, tree ) ) {
            delete tree;
            return false;
        }

        // the next token must be a ';' or a ']'
        tt = lexer.PeekToken();
        if( tt != Lexer::LEX_SEMICOLON && tt != Lexer::LEX_CLOSE_BOX ) {
            CondorErrno = ERR_PARSE_ERROR;
            CondorErrMsg = "while parsing classad:  expected LEX_SEMICOLON or "
                           "LEX_CLOSE_BOX but got " + string( Lexer::strLexToken( tt ) );
            return( false );
        }

        // Slurp up any extra semicolons. This does not duplicate the work at the top of the loop
        // because it accounts for the case where the last expression has extra semicolons,
        // while the first case accounts for optional beginning semicolons.
        while( tt == Lexer::LEX_SEMICOLON ) {
            lexer.ConsumeToken();
            tt = lexer.PeekToken();
        }
    }

    lexer.ConsumeToken();

    // if a full parse was requested, ensure that input is exhausted
    if( full && ( lexer.ConsumeToken() != Lexer::LEX_END_OF_INPUT ) ) {
        CondorErrno = ERR_PARSE_ERROR;
        CondorErrMsg = "while parsing classad:  expected LEX_END_OF_INPUT for "
                       "full parse but got " + string( Lexer::strLexToken( tt ) );
        return false;
    }

    ad.EnableDirtyTracking();
    return true;
}