Example #1
0
static int set_print_mask_from_stream(
	AttrListPrintMask & print_mask,
	std::string & constraint,
	const char * streamid,
	bool is_filename)
{
	StringList attrs;  // used for projection, which we don't currently do. 
	std::string messages;
	printmask_aggregation_t aggregation;
	printmask_headerfooter_t headFoot = STD_HEADFOOT;
	std::vector<GroupByKeyInfo> group_by_keys;
	SimpleInputStream * pstream = NULL;

	FILE *file = NULL;
	if (MATCH == strcmp("-", streamid)) {
		pstream = new SimpleFileInputStream(stdin, false);
	} else if (is_filename) {
		file = safe_fopen_wrapper_follow(streamid, "r");
		if (file == NULL) {
			fprintf(stderr, "Can't open select file: %s\n", streamid);
			return -1;
		}
		pstream = new SimpleFileInputStream(file, true);
	} else {
		pstream = new StringLiteralInputStream(streamid);
	}
	ASSERT(pstream);

	int err = SetAttrListPrintMaskFromStream(
					*pstream,
					LocalPrintFormatsTable,
					print_mask,
					headFoot,
					aggregation,
					group_by_keys,
					constraint,
					attrs,
					messages);
	delete pstream; pstream = NULL;
	if ( ! err) {
		customFormat = true;
		if ( ! constraint.empty()) {
			ExprTree *constraintExpr=NULL;
			if ( ! ParseClassAdRvalExpr(constraint.c_str(), constraintExpr)) {
				formatstr_cat(messages, "WHERE expression is not valid: %s\n", constraint.c_str());
				err = -1;
			} else {
				delete constraintExpr;
			}
		}
		if (aggregation) {
			formatstr_cat(messages, "AUTOCLUSTER or UNIQUE aggregation is not supported.\n");
			err = -1;
		}
	}
	if ( ! messages.empty()) { fprintf(stderr, "%s", messages.c_str()); }
	return err;
}
Example #2
0
void TimerManager::DumpTimerList(int flag, const char* indent)
{
	Timer		*timer_ptr;
	const char	*ptmp;

	// we want to allow flag to be "D_FULLDEBUG | D_DAEMONCORE",
	// and only have output if _both_ are specified by the user
	// in the condor_config.  this is a little different than
	// what dprintf does by itself ( which is just 
	// flag & DebugFlags > 0 ), so our own check here:
	if ( ! IsDebugCatAndVerbosity(flag) )
		return;

	if ( indent == NULL) 
		indent = DEFAULT_INDENT;

	dprintf(flag, "\n");
	dprintf(flag, "%sTimers\n", indent);
	dprintf(flag, "%s~~~~~~\n", indent);
	for(timer_ptr = timer_list; timer_ptr != NULL; timer_ptr = timer_ptr->next)
	{
		if ( timer_ptr->event_descrip )
			ptmp = timer_ptr->event_descrip;
		else
			ptmp = "NULL";

		std::string slice_desc;
		if( !timer_ptr->timeslice ) {
			formatstr(slice_desc, "period = %d, ", timer_ptr->period);
		}
		else {
			formatstr_cat(slice_desc, "timeslice = %.3g, ",
								   timer_ptr->timeslice->getTimeslice());
			if( !IS_ZERO(timer_ptr->timeslice->getDefaultInterval()) ) {
				formatstr_cat(slice_desc, "period = %.1f, ",
								   timer_ptr->timeslice->getDefaultInterval());
			}
			if( !IS_ZERO(timer_ptr->timeslice->getInitialInterval()) ) {
				formatstr_cat(slice_desc, "initial period = %.1f, ",
								   timer_ptr->timeslice->getInitialInterval());
			}
			if( !IS_ZERO(timer_ptr->timeslice->getMinInterval()) ) {
				formatstr_cat(slice_desc, "min period = %.1f, ",
								   timer_ptr->timeslice->getMinInterval());
			}
			if( !IS_ZERO(timer_ptr->timeslice->getMaxInterval()) ) {
				formatstr_cat(slice_desc, "max period = %.1f, ",
								   timer_ptr->timeslice->getMaxInterval());
			}
		}
		dprintf(flag, 
				"%sid = %d, when = %ld, %shandler_descrip=<%s>\n", 
				indent, timer_ptr->id, (long)timer_ptr->when, 
				slice_desc.c_str(),ptmp);
	}
	dprintf(flag, "\n");
}
Example #3
0
INFNBatchResource::INFNBatchResource( const char *batch_type, 
	const char * resource_name )
	: BaseResource( resource_name )
{
	m_batchType = batch_type;
	m_gahpIsRemote = false;

	m_remoteHostname = resource_name;
	size_t pos = m_remoteHostname.find( '@' );
	if ( pos != m_remoteHostname.npos ) {
		m_remoteHostname.erase( 0, pos + 1 );
	}
	
	gahp = NULL;

	std::string gahp_name = batch_type;
	if ( resource_name && *resource_name ) {
		formatstr_cat( gahp_name, "/%s", resource_name );
		m_gahpIsRemote = true;
	}

	gahp = new GahpClient( gahp_name.c_str() );
	gahp->setNotificationTimerId( pingTimerId );
	gahp->setMode( GahpClient::normal );
	gahp->setTimeout( INFNBatchJob::gahpCallTimeout );
}
Example #4
0
const char * INFNBatchResource::HashName( const char * batch_type,
		const char * resource_name )
{
	static std::string hash_name;
	formatstr( hash_name, "batch %s", batch_type );
	if ( resource_name && resource_name[0] ) {
		formatstr_cat( hash_name, " %s", resource_name );
	}
	return hash_name.c_str();
}
Example #5
0
std::string SourceRoute::serialize() {
	std::string rv;
	formatstr( rv, "p=\"%s\"; a=\"%s\"; port=%d; n=\"%s\";", condor_protocol_to_str( p ).c_str(), a.c_str(), port, n.c_str() );
	if(! alias.empty()) { rv += " alias=\"" + alias + "\";"; }
	if(! spid.empty()) { rv += " spid=\"" + spid + "\";"; }
	if(! ccbid.empty()) { rv += " ccbid=\"" + ccbid + "\";"; }
	if(! ccbspid.empty()) { rv += " ccbspid=\"" + ccbspid + "\";"; }
	if( noUDP ) { rv += " noUDP=true;"; }
	if( brokerIndex != -1 ) { formatstr_cat( rv, " brokerIndex=%d;", brokerIndex ); }
	formatstr( rv, "[ %s ]", rv.c_str() );
	return rv;
}
Example #6
0
void CondorResource::CondorRegisterJob( CondorJob *job, const char *submitter_id )
{
	BaseResource::RegisterJob( job );

	if ( submitter_ids.contains( submitter_id ) == false ) {
		submitter_ids.append( submitter_id );
		if ( submitter_constraint.empty() ) {
			formatstr( submitter_constraint, "(%s=?=\"%s\")",
										  ATTR_SUBMITTER_ID,
										  submitter_id );
		} else {
			formatstr_cat( submitter_constraint, "||(%s=?=\"%s\")",
											  ATTR_SUBMITTER_ID,
											  submitter_id );
		}
	}
}
Example #7
0
std::string 
makeHostname(ClassAd *machineAd, ClassAd *jobAd) {
	std::string hostname;

	std::string owner("unknown");
	jobAd->LookupString(ATTR_OWNER, owner);
	
	hostname += owner;

	int cluster = 1;
	int proc = 1;
	jobAd->LookupInteger(ATTR_CLUSTER_ID, cluster);
	jobAd->LookupInteger(ATTR_PROC_ID, proc);
	formatstr_cat(hostname, "-%d.%d-", cluster, proc);

	std::string machine("host");
	machineAd->LookupString(ATTR_MACHINE, machine);

	hostname += machine;

	return hostname;
}
Example #8
0
void BaseResource::UpdateLeases()
{
dprintf(D_FULLDEBUG,"*** UpdateLeases called\n");
	if ( hasLeases == false ) {
dprintf(D_FULLDEBUG,"    Leases not supported, cancelling timer\n" );
		daemonCore->Cancel_Timer( updateLeasesTimerId );
		updateLeasesTimerId = TIMER_UNSET;
		return;
	}

	// Don't start a new lease update too soon after the previous one.
	int delay;
	delay = (lastUpdateLeases + UPDATE_LEASE_DELAY) - time(NULL);
	if ( delay > 0 ) {
		daemonCore->Reset_Timer( updateLeasesTimerId, delay );
dprintf(D_FULLDEBUG,"    UpdateLeases: last update too recent, delaying %d secs\n",delay);
		return;
	}

	daemonCore->Reset_Timer( updateLeasesTimerId, TIMER_NEVER );

    if ( updateLeasesActive == false ) {
		BaseJob *curr_job;
		int new_lease_duration = INT_MAX;
dprintf(D_FULLDEBUG,"    UpdateLeases: calc'ing new leases\n");
		registeredJobs.Rewind();
		while ( registeredJobs.Next( curr_job ) ) {
			int job_lease_duration = m_defaultLeaseDuration;
			curr_job->jobAd->LookupInteger( ATTR_JOB_LEASE_DURATION, job_lease_duration );
			if ( job_lease_duration > 0 && job_lease_duration < new_lease_duration ) {
				new_lease_duration = job_lease_duration;
			}
		}
dprintf(D_FULLDEBUG,"    UpdateLeases: new shared lease duration: %d\n", new_lease_duration );
		// This is how close to the lease expiration time we want to be
		// when we try a renewal.
		int renew_threshold = ( new_lease_duration * 2 / 3 ) + 10;
		if ( new_lease_duration == INT_MAX ||
			 m_sharedLeaseExpiration > time(NULL) + renew_threshold ) {
			// Lease doesn't need renewal, yet.
			time_t next_renew_time = m_sharedLeaseExpiration - renew_threshold;
			if ( new_lease_duration == INT_MAX ||
				 next_renew_time > time(NULL) + 3600 ) {
				next_renew_time = time(NULL) + 3600;
			}
dprintf(D_FULLDEBUG,"    UpdateLeases: nothing to renew, resetting timer for %ld secs\n",next_renew_time - time(NULL));
			lastUpdateLeases = time(NULL);
			daemonCore->Reset_Timer( updateLeasesTimerId,
									 next_renew_time - time(NULL) );
			return;
		} else {
			// Time to renew the lease
			m_sharedLeaseExpiration = time(NULL) + new_lease_duration;
			if ( !m_hasSharedLeases ) {
				registeredJobs.Rewind();
				while ( registeredJobs.Next( curr_job ) ) {
					std::string job_id;
					int tmp;
					if ( curr_job->jobAd->LookupString( ATTR_GRID_JOB_ID, job_id ) &&
						 curr_job->jobAd->LookupInteger( ATTR_JOB_LEASE_DURATION, tmp )
					) {
						leaseUpdates.Append( curr_job );
					}
				}
			}
dprintf(D_FULLDEBUG,"    new shared lease expiration at %ld, performing renewal...\n",m_sharedLeaseExpiration);
			requestScheddUpdateNotification( updateLeasesTimerId );
			updateLeasesActive = true;
		}
	}

	unsigned update_delay = 0;
	bool update_complete;
	SimpleList<PROC_ID> update_succeeded;
	bool update_success;
dprintf(D_FULLDEBUG,"    UpdateLeases: calling DoUpdateLeases\n");
	if ( m_hasSharedLeases ) {
		DoUpdateSharedLease( update_delay, update_complete, update_success );
	} else {
		DoUpdateLeases( update_delay, update_complete, update_succeeded );
	}

	if ( update_delay ) {
		daemonCore->Reset_Timer( updateLeasesTimerId, update_delay );
dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases wants delay of %u secs\n",update_delay);
		return;
	}

	if ( !update_complete ) {
		updateLeasesCmdActive = true;
dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases in progress\n");
		return;
	}

dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases complete, processing results\n");
	bool first_update = lastUpdateLeases == 0;

	updateLeasesCmdActive = false;
	lastUpdateLeases = time(NULL);

	if ( m_hasSharedLeases ) {
		BaseJob *curr_job;
		std::string tmp;
		registeredJobs.Rewind();
		while ( registeredJobs.Next( curr_job ) ) {
			if ( first_update ) {
				// New jobs may be waiting for the lease be to established
				// before they proceed with submission.
				curr_job->SetEvaluateState();
			}
			if ( curr_job->jobAd->LookupString( ATTR_GRID_JOB_ID, tmp ) ) {
				curr_job->UpdateJobLeaseSent( m_sharedLeaseExpiration );
			}
		}
	} else {
std::string msg = "    update_succeeded:";
		BaseJob *curr_job;
		PROC_ID curr_id;
		update_succeeded.Rewind();
		while ( update_succeeded.Next( curr_id ) ) {
formatstr_cat(msg, " %d.%d", curr_id.cluster, curr_id.proc);
			if ( BaseJob::JobsByProcId.lookup( curr_id, curr_job ) == 0 ) {
				curr_job->UpdateJobLeaseSent( m_sharedLeaseExpiration );
			}
		}
dprintf(D_FULLDEBUG,"%s\n",msg.c_str());
		leaseUpdates.Clear();
	}

	updateLeasesActive = false;

dprintf(D_FULLDEBUG,"    UpdateLeases: lease update complete, resetting timer for 30 secs\n");
	daemonCore->Reset_Timer( updateLeasesTimerId, UPDATE_LEASE_DELAY );
}
Example #9
0
int
Starter::execDCStarter( ArgList const &args, Env const *env, 
						int* std_fds, Stream* s )
{
	Stream *inherit_list[] =
		{ 0 /*ClassAd update stream (assigned below)*/,
		  s /*shadow syscall sock*/,
		  0 /*terminal NULL*/ };

	const ArgList* final_args = &args;
	const char* final_path = s_path;
	Env new_env;

	if( env ) {
		new_env.MergeFrom( *env );
	}

		// The starter figures out its execute directory by paraming
		// for EXECUTE, which we override in the environment here.
		// This way, all the logic about choosing a directory to use
		// is in only one place.
	ASSERT( executeDir() );
	new_env.SetEnv( "_CONDOR_EXECUTE", executeDir() );

	env = &new_env;


		// Build the affinity string to pass to the starter via env

	std::string affinityString;
	if (s_claim && s_claim->rip() && s_claim->rip()->get_affinity_set()) {
		std::list<int> *l = s_claim->rip()->get_affinity_set();
		bool needComma = false;
		for (std::list<int>::iterator it = l->begin(); it != l->end(); it++) {
			if (needComma) {
				formatstr_cat(affinityString, ", %d", *it);
			} else {
				formatstr_cat(affinityString, "%d ", *it);
				needComma = true;
			}
		}
	}

	int slotId = s_claim->rip()->r_sub_id;
	if (slotId == 0) {
		// Isn't a paritionable slot, use the main id
		slotId = s_claim->rip()->r_id;
	}
	std::string affinityKnob;
	formatstr(affinityKnob, "_CONDOR_SLOT%d_CPU_AFFINITY",  slotId);

	if (param_boolean("ASSIGN_CPU_AFFINITY", false)) {
		new_env.SetEnv(affinityKnob.c_str(), affinityString.c_str());
		new_env.SetEnv("_CONDOR_ENFORCE_CPU_AFFINITY", "true");
		dprintf(D_FULLDEBUG, "Setting affinity env to %s = %s\n", affinityKnob.c_str(), affinityString.c_str());
	}


	ReliSock child_job_update_sock;   // child inherits this socket
	ASSERT( !s_job_update_sock );
	s_job_update_sock = new ReliSock; // parent (yours truly) keeps this socket
	ASSERT( s_job_update_sock );

		// Connect parent and child sockets together so child can send us
		// udpates to the job ClassAd.
	if( !s_job_update_sock->connect_socketpair( child_job_update_sock ) ) {
		dprintf( D_ALWAYS, "ERROR: Failed to create job ClassAd update socket!\n");
		s_pid = 0;
		return s_pid;
	}
	inherit_list[0] = &child_job_update_sock;

	// Pass the machine ad to the starter
	if (s_claim) 
		s_claim->writeMachAd( s_job_update_sock );

	if( daemonCore->Register_Socket(
			s_job_update_sock,
			"starter ClassAd update socket",
			(SocketHandlercpp)&Starter::receiveJobClassAdUpdate,
			"receiveJobClassAdUpdate",
			this) < 0 )
	{
		EXCEPT("Failed to register ClassAd update socket.");
	}

#if defined(LINUX)
	// see if we should be using glexec to spawn the starter.
	// if we are, the cmd, args, env, and stdin to use will be
	// modified
	ArgList glexec_args;
	Env glexec_env;
	int glexec_std_fds[3];
	if( param_boolean( "GLEXEC_STARTER", false ) ) {
		if( ! glexec_starter_prepare( s_path,
		                              s_claim->client()->proxyFile(),
		                              args,
		                              env,
		                              std_fds,
		                              glexec_args,
		                              glexec_env,
		                              glexec_std_fds ) )
		{
			// something went wrong; prepareForGlexec will
			// have already logged it
			cleanupAfterGlexec();
			return 0;
		}
		final_path = glexec_args.GetArg(0);
		final_args = &glexec_args;
		env = &glexec_env;
		std_fds = glexec_std_fds;
	}
#endif
								   
	int reaper_id;
	if( s_reaper_id > 0 ) {
		reaper_id = s_reaper_id;
	} else {
		reaper_id = main_reaper;
	}

	if(IsFulldebug(D_FULLDEBUG)) {
		MyString args_string;
		final_args->GetArgsStringForDisplay(&args_string);
		dprintf( D_FULLDEBUG, "About to Create_Process \"%s\"\n",
				 args_string.Value() );
	}

	FamilyInfo fi;
	fi.max_snapshot_interval = pid_snapshot_interval;

	s_pid = daemonCore->
		Create_Process( final_path, *final_args, PRIV_ROOT, reaper_id,
		                TRUE, env, NULL, &fi, inherit_list, std_fds );
	if( s_pid == FALSE ) {
		dprintf( D_ALWAYS, "ERROR: exec_starter failed!\n");
		s_pid = 0;
	}

#if defined(LINUX)
	if( param_boolean( "GLEXEC_STARTER", false ) ) {
		// if we used glexec to spawn the Starter, we now need to send
		// the Starter's environment to our glexec wrapper script so it
		// can exec the Starter with all the environment variablew we rely
		// on it inheriting
		//
		if ( !glexec_starter_handle_env(s_pid) ) {
			// something went wrong; handleGlexecEnvironment will
			// have already logged it
			cleanupAfterGlexec();
			return 0;
		}
	}
#endif

	return s_pid;
}
Example #10
0
// Read a stream a line at a time, and parse it to fill out the print mask,
// header, group_by, where expression, and projection attributes.
//
int SetAttrListPrintMaskFromStream (
	SimpleInputStream & stream, // in: fetch lines from this stream until nextline() returns NULL
	const CustomFormatFnTable & FnTable, // in: table of custom output functions for SELECT
	AttrListPrintMask & mask, // out: columns and headers set in SELECT
	printmask_headerfooter_t & headfoot, // out: header and footer flags set in SELECT or SUMMARY
	printmask_aggregation_t & aggregate, // out: aggregation mode in SELECT
	std::vector<GroupByKeyInfo> & group_by, // out: ordered set of attributes/expressions in GROUP BY
	std::string & where_expression, // out: classad expression from WHERE
	StringList & attrs, // out ClassAd attributes referenced in mask or group_by outputs
	std::string & error_message) // out, if return is non-zero, this will be an error message
{
	ClassAd ad; // so we can GetExprReferences
	enum section_t { NOWHERE=0, SELECT, SUMMARY, WHERE, GROUP};
	enum cust_t { PRINTAS_STRING, PRINTAS_INT, PRINTAS_FLOAT };

	bool label_fields = false;
	const char * labelsep = " = ";
	const char * prowpre = NULL;
	const char * pcolpre = " ";
	const char * pcolsux = NULL;
	const char * prowsux = "\n";
	mask.SetAutoSep(prowpre, pcolpre, pcolsux, prowsux);

	error_message.clear();
	aggregate = PR_NO_AGGREGATION;

	printmask_headerfooter_t usingHeadFoot = (printmask_headerfooter_t)(HF_CUSTOM | HF_NOSUMMARY);
	section_t sect = SELECT;
	tokener toke("");
	while (toke.set(stream.nextline())) {
		if ( ! toke.next())
			continue;

		if (toke.matches("#")) continue;

		if (toke.matches("SELECT"))	{
			while (toke.next()) {
				if (toke.matches("FROM")) {
					if (toke.next()) {
						if (toke.matches("AUTOCLUSTER")) {
							aggregate = PR_FROM_AUTOCLUSTER;
						} else {
							std::string aa; toke.copy_token(aa);
							formatstr_cat(error_message, "Warning: Unknown header argument %s for SELECT FROM\n", aa.c_str());
						}
					}
				} else if (toke.matches("UNIQUE")) {
					aggregate = PR_COUNT_UNIQUE;
				} else if (toke.matches("BARE")) {
					usingHeadFoot = HF_BARE;
				} else if (toke.matches("NOTITLE")) {
					usingHeadFoot = (printmask_headerfooter_t)(usingHeadFoot | HF_NOTITLE);
				} else if (toke.matches("NOHEADER")) {
					usingHeadFoot = (printmask_headerfooter_t)(usingHeadFoot | HF_NOHEADER);
				} else if (toke.matches("NOSUMMARY")) {
					usingHeadFoot = (printmask_headerfooter_t)(usingHeadFoot | HF_NOSUMMARY);
				} else if (toke.matches("LABEL")) {
					label_fields = true;
				} else if (label_fields && toke.matches("SEPARATOR")) {
					if (toke.next()) { std::string tmp; toke.copy_token(tmp); collapse_escapes(tmp); labelsep = mask.store(tmp.c_str()); }
				} else if (toke.matches("RECORDPREFIX")) {
					if (toke.next()) { std::string tmp; toke.copy_token(tmp); collapse_escapes(tmp); prowpre = mask.store(tmp.c_str()); }
				} else if (toke.matches("RECORDSUFFIX")) {
					if (toke.next()) { std::string tmp; toke.copy_token(tmp); collapse_escapes(tmp); prowsux = mask.store(tmp.c_str()); }
				} else if (toke.matches("FIELDPREFIX")) {
					if (toke.next()) { std::string tmp; toke.copy_token(tmp); collapse_escapes(tmp); pcolpre = mask.store(tmp.c_str()); }
				} else if (toke.matches("FIELDSUFFIX")) {
					if (toke.next()) { std::string tmp; toke.copy_token(tmp); collapse_escapes(tmp); pcolsux = mask.store(tmp.c_str()); }
				} else {
					std::string aa; toke.copy_token(aa);
					formatstr_cat(error_message, "Warning: Unknown header argument %s for SELECT\n", aa.c_str());
				}
			}
			mask.SetAutoSep(prowpre, pcolpre, pcolsux, prowsux);
			sect = SELECT;
			continue;
		} else if (toke.matches("WHERE")) {
			sect = WHERE;
			if ( ! toke.next()) continue;
		} else if (toke.matches("GROUP")) {
			sect = GROUP;
			if ( ! toke.next() || (toke.matches("BY") && ! toke.next())) continue;
		} else if (toke.matches("SUMMARY")) {
			usingHeadFoot = (printmask_headerfooter_t)(usingHeadFoot & ~HF_NOSUMMARY);
			while (toke.next()) {
				if (toke.matches("STANDARD")) {
					// attrs.insert(ATTR_JOB_STATUS);
				} else if (toke.matches("NONE")) {
					usingHeadFoot = (printmask_headerfooter_t)(usingHeadFoot | HF_NOSUMMARY);
				} else {
					std::string aa; toke.copy_token(aa);
					formatstr_cat(error_message, "Unknown argument %s for SELECT\n", aa.c_str());
				}
			}
			sect = SUMMARY;
			continue;
		}

		switch (sect) {
		case SELECT: {
			toke.mark();
			std::string attr;
			std::string name;
			int opts = FormatOptionAutoWidth | FormatOptionNoTruncate;
			const char * fmt = "%v";
			int wid = 0;
			CustomFormatFn cust;

			bool got_attr = false;
			while (toke.next()) {
				const Keyword * pkw = SelectKeywords.find_match(toke);
				if ( ! pkw)
					continue;

				// next token is a keyword, if we havent set the attribute yet
				// it's everything up to the current token.
				int kw = pkw->value;
				if ( ! got_attr) {
					toke.copy_marked(attr);
					got_attr = true;
				}

				switch (kw) {
				case kw_AS: {
					if (toke.next()) {
						toke.copy_token(name);
						if (toke.is_quoted_string()) { collapse_escapes(name); }
					} else {
						expected_token(error_message, "column name after AS", "SELECT", stream, toke);
					}
					toke.mark_after();
				} break;
				case kw_PRINTF: {
					if (toke.next()) {
						std::string val; toke.copy_token(val);
						fmt = mask.store(val.c_str());
					} else {
						expected_token(error_message, "format after PRINTF", "SELECT", stream, toke);
					}
				} break;
				case kw_PRINTAS: {
					if (toke.next()) {
						const CustomFormatFnTableItem * pcffi = FnTable.find_match(toke);
						if (pcffi) {
							cust = pcffi->cust;
							//cust_type = pcffi->cust;
							const char * pszz = pcffi->extra_attribs;
							if (pszz) {
								size_t cch = strlen(pszz);
								while (cch > 0) { attrs.insert(pszz); pszz += cch+1; cch = strlen(pszz); }
							}
						} else {
							std::string aa; toke.copy_token(aa);
							formatstr_cat(error_message, "Unknown argument %s for PRINTAS\n", aa.c_str());
						}
					} else {
						expected_token(error_message, "function name after PRINTAS", "SELECT", stream, toke);
					}
				} break;
				case kw_NOSUFFIX: {
					opts |= FormatOptionNoSuffix;
				} break;
				case kw_NOPREFIX: {
					opts |= FormatOptionNoPrefix;
				} break;
				case kw_LEFT: {
					opts |= FormatOptionLeftAlign;
				} break;
				case kw_RIGHT: {
					opts &= ~FormatOptionLeftAlign;
				} break;
				case kw_TRUNCATE: {
					opts &= ~FormatOptionNoTruncate;
				} break;
				case kw_WIDTH: {
					if (toke.next()) {
						std::string val; toke.copy_token(val);
						if (toke.matches("AUTO")) {
							opts |= FormatOptionAutoWidth;
						} else {
							wid = atoi(val.c_str());
							//if (wid) opts &= ~FormatOptionAutoWidth;
							//PRAGMA_REMIND("TJ: decide how LEFT & RIGHT interact with pos and neg widths."
						}
					} else {
						expected_token(error_message, "number or AUTO after WIDTH", "SELECT", stream, toke);
					}
				} break;
				default:
					unexpected_token(error_message, "SELECT", stream, toke);
				break;
				} // switch
			} // while

			if ( ! got_attr) { attr = toke.content(); }
			trim(attr);
			if (attr.empty() || attr[0] == '#') continue;

			const char * lbl = name.empty() ? attr.c_str() : name.c_str();
			if (label_fields) {
				// build a format string that contains the label
				std::string label(lbl);
				if (labelsep) { label += labelsep; }
				if (fmt) { label += fmt; } 
				else {
					label += "%";
					if (wid) {
						if (opts & FormatOptionNoTruncate)
							formatstr_cat(label, "%d", wid);
						else
							formatstr_cat(label, "%d.%d", wid, wid < 0 ? -wid : wid);
					}
					label += cust ? "s" : "v";
				}
				lbl = mask.store(label.c_str());
				fmt = lbl;
				wid = 0;
			} else {
				if ( ! wid) { wid = 0 - (int)strlen(lbl); }
				mask.set_heading(lbl);
				lbl = NULL;
			}
			if (cust) {
				mask.registerFormat (lbl, wid, opts, cust, attr.c_str());
			} else {
				mask.registerFormat(fmt, wid, opts, attr.c_str());
			}
			ad.GetExprReferences(attr.c_str(), NULL, &attrs);
		}
		break;

		case WHERE: {
			toke.copy_to_end(where_expression);
			trim(where_expression);
		}
		break;

		case SUMMARY: {
		}
		break;

		case GROUP: {
			toke.mark();
			GroupByKeyInfo key;

			// in case we end up finding no keywords, copy the remainder of the line now as the expression
			toke.copy_to_end(key.expr);
			bool got_expr = false;

			while (toke.next()) {
				const Keyword * pgw = GroupKeywords.find_match(toke);
				if ( ! pgw)
					continue;

				// got a keyword
				int gw = pgw->value;
				if ( ! got_expr) {
					toke.copy_marked(key.expr);
					got_expr = true;
				}

				switch (gw) {
				case gw_AS: {
					if (toke.next()) { toke.copy_token(key.name); }
					toke.mark_after();
				} break;
				case gw_DECENDING: {
					key.decending = true;
					toke.mark_after();
				} break;
				case gw_ASCENDING: {
					key.decending = false;
					toke.mark_after();
				} break;
				default:
					unexpected_token(error_message, "GROUP BY", stream, toke);
				break;
				} // switch
			} // while toke.next

			trim(key.expr);
			if (key.expr.empty() || key.expr[0] == '#')
				continue;

			if ( ! ad.GetExprReferences(key.expr.c_str(), NULL, &attrs)) {
				formatstr_cat(error_message, "GROUP BY expression is not valid: %s\n", key.expr.c_str());
			} else {
				group_by.push_back(key);
			}
		}
		break;

		default:
		break;
		}
	}

	headfoot = usingHeadFoot;

	return 0;
}
Example #11
0
static void expected_token(std::string & message, const char * reason, const char * tag, SimpleInputStream & stream, tokener & toke)
{
	std::string tok; toke.copy_token(tok);
	formatstr_cat(message, "expected %s at line %d offset %d in %s\n",
		reason, stream.count_of_lines_read(), (int)toke.offset(), tag);
}
Example #12
0
int
Starter::execDCStarter( ArgList const &args, Env const *env, 
						int* std_fds, Stream* s )
{
	Stream *inherit_list[] =
		{ 0 /*ClassAd update stream (assigned below)*/,
		  s /*shadow syscall sock*/,
		  0 /*terminal NULL*/ };

	const ArgList* final_args = &args;
	const char* final_path = s_path;
	Env new_env;

	if( env ) {
		new_env.MergeFrom( *env );
	}

		// The starter figures out its execute directory by paraming
		// for EXECUTE, which we override in the environment here.
		// This way, all the logic about choosing a directory to use
		// is in only one place.
	ASSERT( executeDir() );
	new_env.SetEnv( "_CONDOR_EXECUTE", executeDir() );

		// Handle encrypted execute directory
	FilesystemRemap  fs_remap_obj;	// put on stack so destroyed when leave this method
	FilesystemRemap* fs_remap = NULL;
	// If admin desires encrypted exec dir in config, do it
	bool encrypt_execdir = param_boolean_crufty("ENCRYPT_EXECUTE_DIRECTORY",false);
	// Or if user wants encrypted exec in job ad, do it
	if (!encrypt_execdir && s_claim->ad()) {
		s_claim->ad()->LookupBool(ATTR_ENCRYPT_EXECUTE_DIRECTORY,encrypt_execdir);
	}
	if ( encrypt_execdir ) {
#ifdef LINUX
		// On linux, setup a directory $EXECUTE/encryptedX subdirectory
		// to serve as an ecryptfs mount point; pass this directory
		// down to the condor_starter as if it were $EXECUTE so
		// that the starter creates its dir_<pid> directory on the
		// ecryptfs filesystem setup by doing an AddEncryptedMapping.
		static int unsigned long privdirnum = 0;
		TemporaryPrivSentry sentry(PRIV_CONDOR);
		s_encrypted_execute_dir.formatstr("%s%cencrypted%lu",executeDir(),
				DIR_DELIM_CHAR,privdirnum++);
		if( mkdir(encryptedExecuteDir(), 0755) < 0 ) {
			dprintf( D_FAILURE|D_ALWAYS,
			         "Failed to create encrypted dir %s: %s\n",
			         encryptedExecuteDir(),
			         strerror(errno) );
			return 0;
		}
		dprintf( D_ALWAYS,
		         "Created encrypted dir %s\n", encryptedExecuteDir() );
		fs_remap = &fs_remap_obj;
		if ( fs_remap->AddEncryptedMapping(encryptedExecuteDir()) ) {
			// FilesystemRemap object dprintfs out an error message for us
			return 0;
		}
		new_env.SetEnv( "_CONDOR_EXECUTE", encryptedExecuteDir() );
#endif
	}

	env = &new_env;


		// Build the affinity string to pass to the starter via env

	std::string affinityString;
	if (s_claim && s_claim->rip() && s_claim->rip()->get_affinity_set()) {
		std::list<int> *l = s_claim->rip()->get_affinity_set();
		bool needComma = false;
		for (std::list<int>::iterator it = l->begin(); it != l->end(); it++) {
			if (needComma) {
				formatstr_cat(affinityString, ", %d", *it);
			} else {
				formatstr_cat(affinityString, "%d ", *it);
				needComma = true;
			}
		}
	}

	bool affinityBool = false;
	if ( ! s_claim || ! s_claim->ad()) {
		affinityBool = param_boolean("ASSIGN_CPU_AFFINITY", false);
	} else {
		auto_free_ptr assign_cpu_affinity(param("ASSIGN_CPU_AFFINITY"));
		if ( ! assign_cpu_affinity.empty()) {
			classad::Value value;
			if (s_claim->ad()->EvaluateExpr(assign_cpu_affinity.ptr(), value)) {
				if ( ! value.IsBooleanValueEquiv(affinityBool)) {
					// was an expression, but not a bool, so report it and continue
					EXCEPT("ASSIGN_CPU_AFFINITY does not evaluate to a boolean, it is : %s", ClassAdValueToString(value));
				}
			}
		}
	}

	if (affinityBool) {
		new_env.SetEnv("_CONDOR_STARTD_ASSIGNED_AFFINITY", affinityString.c_str());
		new_env.SetEnv("_CONDOR_ENFORCE_CPU_AFFINITY", "true");
		dprintf(D_ALWAYS, "Setting affinity env to %s\n", affinityString.c_str());
	}


	ReliSock child_job_update_sock;   // child inherits this socket
	ASSERT( !s_job_update_sock );
	s_job_update_sock = new ReliSock; // parent (yours truly) keeps this socket
	ASSERT( s_job_update_sock );

		// Connect parent and child sockets together so child can send us
		// udpates to the job ClassAd.
	if( !s_job_update_sock->connect_socketpair( child_job_update_sock ) ) {
		dprintf( D_ALWAYS, "ERROR: Failed to create job ClassAd update socket!\n");
		s_pid = 0;
		return s_pid;
	}
	inherit_list[0] = &child_job_update_sock;

	// Pass the machine ad to the starter
	if (s_claim) 
		s_claim->writeMachAd( s_job_update_sock );

	if( daemonCore->Register_Socket(
			s_job_update_sock,
			"starter ClassAd update socket",
			(SocketHandlercpp)&Starter::receiveJobClassAdUpdate,
			"receiveJobClassAdUpdate",
			this) < 0 )
	{
		EXCEPT("Failed to register ClassAd update socket.");
	}

#if defined(LINUX)
	// see if we should be using glexec to spawn the starter.
	// if we are, the cmd, args, env, and stdin to use will be
	// modified
	ArgList glexec_args;
	Env glexec_env;
	int glexec_std_fds[3];
	if( param_boolean( "GLEXEC_STARTER", false ) ) {
		if( ! glexec_starter_prepare( s_path,
		                              s_claim->client()->proxyFile(),
		                              args,
		                              env,
		                              std_fds,
		                              glexec_args,
		                              glexec_env,
		                              glexec_std_fds ) )
		{
			// something went wrong; prepareForGlexec will
			// have already logged it
			cleanupAfterGlexec();
			return 0;
		}
		final_path = glexec_args.GetArg(0);
		final_args = &glexec_args;
		env = &glexec_env;
		std_fds = glexec_std_fds;
	}
#endif
								   
	int reaper_id;
	if( s_reaper_id > 0 ) {
		reaper_id = s_reaper_id;
	} else {
		reaper_id = main_reaper;
	}

	if(IsFulldebug(D_FULLDEBUG)) {
		MyString args_string;
		final_args->GetArgsStringForDisplay(&args_string);
		dprintf( D_FULLDEBUG, "About to Create_Process \"%s\"\n",
				 args_string.Value() );
	}

	FamilyInfo fi;
	fi.max_snapshot_interval = pid_snapshot_interval;

	s_pid = daemonCore->
		Create_Process( final_path, *final_args, PRIV_ROOT, reaper_id,
		                TRUE, TRUE, env, NULL, &fi, inherit_list, std_fds,
						NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, fs_remap);
	if( s_pid == FALSE ) {
		dprintf( D_ALWAYS, "ERROR: exec_starter failed!\n");
		s_pid = 0;
	}

#if defined(LINUX)
	if( param_boolean( "GLEXEC_STARTER", false ) ) {
		// if we used glexec to spawn the Starter, we now need to send
		// the Starter's environment to our glexec wrapper script so it
		// can exec the Starter with all the environment variablew we rely
		// on it inheriting
		//
		if ( !glexec_starter_handle_env(s_pid) ) {
			// something went wrong; handleGlexecEnvironment will
			// have already logged it
			cleanupAfterGlexec();
			return 0;
		}
	}
#endif

	return s_pid;
}
Example #13
0
void BaseResource::UpdateLeases()
{
dprintf(D_FULLDEBUG,"*** UpdateLeases called\n");
	if ( hasLeases == false ) {
dprintf(D_FULLDEBUG,"    Leases not supported, cancelling timer\n" );
		daemonCore->Cancel_Timer( updateLeasesTimerId );
		updateLeasesTimerId = TIMER_UNSET;
		return;
	}

	// Don't start a new lease update too soon after the previous one.
	int delay;
	delay = (lastUpdateLeases + UPDATE_LEASE_DELAY) - time(NULL);
	if ( delay > 0 ) {
		daemonCore->Reset_Timer( updateLeasesTimerId, delay );
dprintf(D_FULLDEBUG,"    UpdateLeases: last update too recent, delaying %d secs\n",delay);
		return;
	}

	daemonCore->Reset_Timer( updateLeasesTimerId, TIMER_NEVER );

    if ( updateLeasesActive == false ) {
		BaseJob *curr_job;
		time_t next_renew_time = INT_MAX;
		time_t job_renew_time;
		int min_new_expire = INT_MAX;
dprintf(D_FULLDEBUG,"    UpdateLeases: calc'ing new leases\n");
		registeredJobs.Rewind();
dprintf(D_FULLDEBUG,"    starting min_new_expire=%d next_renew_time=%ld\n",min_new_expire,next_renew_time);
		while ( registeredJobs.Next( curr_job ) ) {
			int new_expire;
			std::string  job_id;
			job_renew_time = next_renew_time;
				// Don't update the lease for a job that isn't submitted
				// anywhere. The Job object will start the lease when it
				// submits the job.
			if ( ( m_hasSharedLeases || curr_job->jobAd->LookupString( ATTR_GRID_JOB_ID, job_id ) ) &&
				 CalculateJobLease( curr_job->jobAd, new_expire,
									m_defaultLeaseDuration,
									&job_renew_time ) ) {

				if ( new_expire < min_new_expire ) {
					min_new_expire = new_expire;
				}
				if ( !m_hasSharedLeases ) {
					curr_job->UpdateJobLeaseSent( new_expire );
					leaseUpdates.Append( curr_job );
				}
			} else if ( job_renew_time < next_renew_time ) {
				next_renew_time = job_renew_time;
			}
dprintf(D_FULLDEBUG,"    after %d.%d: min_new_expire=%d next_renew_time=%ld job_renew_time=%ld\n",curr_job->procID.cluster,curr_job->procID.proc,min_new_expire,next_renew_time,job_renew_time);
		}
		if ( min_new_expire == INT_MAX ||
			 ( m_hasSharedLeases && next_renew_time < INT_MAX &&
			   m_sharedLeaseExpiration != 0 ) ) {
			if ( next_renew_time > time(NULL) + 3600 ) {
				next_renew_time = time(NULL) + 3600;
			}
dprintf(D_FULLDEBUG,"    UpdateLeases: nothing to renew, resetting timer for %ld secs\n",next_renew_time - time(NULL));
			lastUpdateLeases = time(NULL);
			daemonCore->Reset_Timer( updateLeasesTimerId,
									 next_renew_time - time(NULL) );
		} else {
			if ( m_hasSharedLeases ) {
				registeredJobs.Rewind();
				while ( registeredJobs.Next( curr_job ) ) {
					std::string job_id;
					if ( curr_job->jobAd->LookupString( ATTR_GRID_JOB_ID, job_id ) ) {
						curr_job->UpdateJobLeaseSent( min_new_expire );
					}
				}
				m_sharedLeaseExpiration = min_new_expire;
dprintf(D_FULLDEBUG,"    new shared lease expiration at %ld, updating job ads...\n",m_sharedLeaseExpiration);
			}
			requestScheddUpdateNotification( updateLeasesTimerId );
			updateLeasesActive = true;
			leaseAttrsSynched = false;
		}
		return;
	}

	if ( leaseAttrsSynched == false ) {
		bool still_dirty = false;
		BaseJob *curr_job;
		leaseUpdates.Rewind();
		while ( leaseUpdates.Next( curr_job ) ) {
			bool exists, dirty;
			curr_job->jobAd->GetDirtyFlag( ATTR_JOB_LEASE_EXPIRATION,
										   &exists, &dirty );
			if ( !exists ) {
					// What!? The attribute disappeared? Forget about renewing
					// the lease then
				dprintf( D_ALWAYS, "Lease attribute disappeared for job %d.%d, ignoring it\n",
						 curr_job->procID.cluster, curr_job->procID.proc );
				leaseUpdates.DeleteCurrent();
			}
			if ( dirty ) {
				still_dirty = true;
				requestScheddUpdate( curr_job, false );
			}
		}
		if ( still_dirty ) {
			requestScheddUpdateNotification( updateLeasesTimerId );
dprintf(D_FULLDEBUG,"    UpdateLeases: waiting for schedd synch\n");
			return;
		}
else dprintf(D_FULLDEBUG,"    UpdateLeases: leases synched\n");
	}

	leaseAttrsSynched = true;

	unsigned update_delay = 0;
	bool update_complete;
	SimpleList<PROC_ID> update_succeeded;
	bool update_success;
dprintf(D_FULLDEBUG,"    UpdateLeases: calling DoUpdateLeases\n");
	if ( m_hasSharedLeases ) {
		DoUpdateSharedLease( update_delay, update_complete, update_success );
	} else {
		DoUpdateLeases( update_delay, update_complete, update_succeeded );
	}

	if ( update_delay ) {
		daemonCore->Reset_Timer( updateLeasesTimerId, update_delay );
dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases wants delay of %uld secs\n",update_delay);
		return;
	}

	if ( !update_complete ) {
		updateLeasesCmdActive = true;
dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases in progress\n");
		return;
	}

dprintf(D_FULLDEBUG,"    UpdateLeases: DoUpdateLeases complete, processing results\n");
	bool first_update = lastUpdateLeases == 0;

	updateLeasesCmdActive = false;
	lastUpdateLeases = time(NULL);

	if ( m_hasSharedLeases ) {
		BaseJob *curr_job;
		std::string tmp;
		registeredJobs.Rewind();
		while ( registeredJobs.Next( curr_job ) ) {
			if ( first_update ) {
				// New jobs may be waiting for the lease be to established
				// before they proceed with submission.
				curr_job->SetEvaluateState();
			}
			if ( !curr_job->jobAd->LookupString( ATTR_GRID_JOB_ID, tmp ) ) {
				continue;
			}
			bool curr_renewal_failed = !update_success;
			bool last_renewal_failed = false;
			curr_job->jobAd->LookupBool( ATTR_LAST_JOB_LEASE_RENEWAL_FAILED,
										 last_renewal_failed );
			if ( curr_renewal_failed != last_renewal_failed ) {
				curr_job->jobAd->Assign( ATTR_LAST_JOB_LEASE_RENEWAL_FAILED,
										 curr_renewal_failed );
				requestScheddUpdate( curr_job, false );
			}
		}
	} else {
update_succeeded.Rewind();
PROC_ID id;
std::string msg = "    update_succeeded:";
 while(update_succeeded.Next(id)) formatstr_cat(msg, " %d.%d", id.cluster, id.proc);
dprintf(D_FULLDEBUG,"%s\n",msg.c_str());
		BaseJob *curr_job;
		leaseUpdates.Rewind();
		while ( leaseUpdates.Next( curr_job ) ) {
			bool curr_renewal_failed;
			bool last_renewal_failed = false;
			if ( update_succeeded.IsMember( curr_job->procID ) ) {
dprintf(D_FULLDEBUG,"    %d.%d is in succeeded list\n",curr_job->procID.cluster,curr_job->procID.proc);
				curr_renewal_failed = false;
			} else {
dprintf(D_FULLDEBUG,"    %d.%d is not in succeeded list\n",curr_job->procID.cluster,curr_job->procID.proc);
				curr_renewal_failed = true;
			}
			curr_job->jobAd->LookupBool( ATTR_LAST_JOB_LEASE_RENEWAL_FAILED,
										 last_renewal_failed );
			if ( curr_renewal_failed != last_renewal_failed ) {
				curr_job->jobAd->Assign( ATTR_LAST_JOB_LEASE_RENEWAL_FAILED,
										 curr_renewal_failed );
				requestScheddUpdate( curr_job, false );
			}
			leaseUpdates.DeleteCurrent();
		}
	}

	updateLeasesActive = false;

dprintf(D_FULLDEBUG,"    UpdateLeases: lease update complete, resetting timer for 30 secs\n");
	daemonCore->Reset_Timer( updateLeasesTimerId, UPDATE_LEASE_DELAY );
}
Example #14
0
int
SharedPortClient::PassSocket(Sock *sock_to_pass,char const *shared_port_id,char const *requested_by, bool non_blocking)
{
#ifndef HAVE_SHARED_PORT

	dprintf(D_ALWAYS,"SharedPortClient::PassSocket() not supported on this platform\n");
	SharedPortClient::m_failPassSocketCalls++;
	return FALSE;

#elif WIN32

	/* Handle Windows */

	if( !SharedPortIdIsValid(shared_port_id) ) {
		dprintf(D_ALWAYS,
				"ERROR: SharedPortClient: refusing to connect to shared port"
				"%s, because specified id is illegal! (%s)\n",
				requested_by, shared_port_id );
		SharedPortClient::m_failPassSocketCalls++;
		return FALSE;
	}

	std::string pipe_name;
	SharedPortEndpoint::GetDaemonSocketDir(pipe_name);
	formatstr_cat(pipe_name, "%c%s", DIR_DELIM_CHAR, shared_port_id);

	MyString requested_by_buf;
	if( !requested_by ) {
		requested_by_buf.formatstr(
			" as requested by %s", sock_to_pass->peer_description());
		requested_by = requested_by_buf.Value();
	}

	HANDLE child_pipe;
	
	while(true)
	{
		child_pipe = CreateFile(
			pipe_name.c_str(),
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			0,
			NULL);

		if(child_pipe != INVALID_HANDLE_VALUE)
			break;

		if(GetLastError() == ERROR_PIPE_BUSY)
		{
			dprintf(D_FULLDEBUG, "SharedPortClient: pipe id '%s' %s is busy, waiting\n", shared_port_id, requested_by);
		#if 1 // tj: this *might*? make a difference?
			bool timeout = true;
			for (int ii = 0; ii < 5; ++ii) {
				if (WaitNamedPipe(pipe_name.c_str(), 3 * 1000)) { timeout = false; break; }
				DWORD err = GetLastError();
				dprintf(D_FULLDEBUG, "SharedPortClient: pipe id '%s' %s wait returned %d\n", shared_port_id, requested_by, err);
			}
			if (timeout)
		#else
			if (!WaitNamedPipe(pipe_name.c_str(), 20 * 1000))
		#endif
			{
				DWORD err = GetLastError();
				dprintf(D_ALWAYS, "ERROR: SharedPortClient: Wait for named pipe id '%s' %s for sending failed: %d %s\n",
					shared_port_id, requested_by, err, GetLastErrorString(err));
				SharedPortClient::m_failPassSocketCalls++;
				return FALSE;
			}
			dprintf(D_FULLDEBUG, "SharedPortClient: wait for pipe id '%s' %s succeeded.\n", shared_port_id, requested_by);
		}
		else
		{
			DWORD err = GetLastError();
			dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to open named pipe id '%s' %s for sending socket: %d %s\n", 
				shared_port_id, requested_by, err, GetLastErrorString(err));
			SharedPortClient::m_failPassSocketCalls++;
			return FALSE;
		}
	}

	DWORD child_pid;
	DWORD read_bytes = 0;

	BOOL read_result = ReadFile(child_pipe, &child_pid, sizeof(DWORD), &read_bytes, NULL);

	if(!read_result)
	{
		DWORD last_error = GetLastError();
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to read PID from pipe: %d.\n", last_error);
		CloseHandle(child_pipe);
		SharedPortClient::m_failPassSocketCalls++;
		return FALSE;
	}
	else
	{
		dprintf(D_FULLDEBUG, "SharedPortClient: Read PID: %d\n", child_pid);
	}

	#pragma pack(push, 4)
	struct {
		int id; // condor commmand id
		WSAPROTOCOL_INFO wsa; // payload.
	} protocol_command;
	#pragma pack(pop)
	ZeroMemory(&protocol_command, sizeof(protocol_command));

	int dup_result = WSADuplicateSocket(sock_to_pass->get_file_desc(), child_pid, &protocol_command.wsa);
	if(dup_result == SOCKET_ERROR)
	{
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to duplicate socket.\n");
		CloseHandle(child_pipe);
		SharedPortClient::m_failPassSocketCalls++;
		return FALSE;
	}

	protocol_command.id = SHARED_PORT_PASS_SOCK;
	BOOL write_result = WriteFile(child_pipe, &protocol_command, sizeof(protocol_command), &read_bytes, 0);

	if(!write_result)
	{
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to send WSAPROTOCOL_INFO struct: %d\n", GetLastError());
		CloseHandle(child_pipe);
		SharedPortClient::m_failPassSocketCalls++;
		return FALSE;
	}
	dprintf(D_FULLDEBUG, "SharedPortClient: Wrote %d bytes to named pipe.\n", read_bytes);
	FlushFileBuffers(child_pipe);

	CloseHandle(child_pipe);

	SharedPortClient::m_successPassSocketCalls++;
	return TRUE;

#elif HAVE_SCM_RIGHTS_PASSFD

	/* Handle most (all?) Linux/Unix and MacOS platforms */

	SharedPortState * state = new SharedPortState(static_cast<ReliSock*>(sock_to_pass),
									shared_port_id, requested_by, non_blocking);

	int result = state->Handle();

	switch (result) 
	{
	case KEEP_STREAM:
		// pass thru so that we return KEEP_STREAM; the PassSocket call is
		// pending, we want to keep the passed socket open until we get an 
		// ack from endpoint.  
		ASSERT( non_blocking ); // should only get KEEP_STREAM if non_blocking is true
		break;
	case SharedPortState::FAILED:
		result = FALSE;
		break;
	case SharedPortState::DONE:
		result = TRUE;
		break;
	case SharedPortState::CONTINUE:
	case SharedPortState::WAIT:
	default:
		// coding logic error if Handle() returns anything else
		EXCEPT("ERROR SharedPortState::Handle() unexpected return code %d",result);
		break;
	}

	return result;

#else

#error HAVE_SHARED_PORT is defined, but no method for passing fds is enabled.

#endif
}
Example #15
0
std::string *NordugridJob::buildSubmitRSL()
{
	int transfer_exec = TRUE;
	std::string *rsl = new std::string;
	StringList *stage_list = NULL;
	StringList *stage_local_list = NULL;
	char *attr_value = NULL;
	std::string rsl_suffix;
	std::string iwd;
	std::string executable;

	if ( jobAd->LookupString( ATTR_NORDUGRID_RSL, rsl_suffix ) &&
						   rsl_suffix[0] == '&' ) {
		*rsl = rsl_suffix;
		return rsl;
	}

	if ( jobAd->LookupString( ATTR_JOB_IWD, iwd ) != 1 ) {
		errorString = "ATTR_JOB_IWD not defined";
		delete rsl;
		return NULL;
	}

	//Start off the RSL
	attr_value = param( "FULL_HOSTNAME" );
	formatstr( *rsl, "&(savestate=yes)(action=request)(hostname=%s)", attr_value );
	free( attr_value );
	attr_value = NULL;

	//We're assuming all job clasads have a command attribute
	jobAd->LookupString( ATTR_JOB_CMD, executable );
	jobAd->LookupBool( ATTR_TRANSFER_EXECUTABLE, transfer_exec );

	*rsl += "(executable=";
	// If we're transferring the executable, strip off the path for the
	// remote machine, since it refers to the submit machine.
	if ( transfer_exec ) {
		*rsl += condor_basename( executable.c_str() );
	} else {
		*rsl += executable;
	}

	{
		ArgList args;
		MyString arg_errors;
		MyString rsl_args;
		if(!args.AppendArgsFromClassAd(jobAd,&arg_errors)) {
			dprintf(D_ALWAYS,"(%d.%d) Failed to read job arguments: %s\n",
					procID.cluster, procID.proc, arg_errors.Value());
			formatstr(errorString,"Failed to read job arguments: %s\n",
					arg_errors.Value());
			delete rsl;
			return NULL;
		}
		if(args.Count() != 0) {
			if(args.InputWasV1()) {
					// In V1 syntax, the user's input _is_ RSL
				if(!args.GetArgsStringV1Raw(&rsl_args,&arg_errors)) {
					dprintf(D_ALWAYS,
							"(%d.%d) Failed to get job arguments: %s\n",
							procID.cluster,procID.proc,arg_errors.Value());
					formatstr(errorString,"Failed to get job arguments: %s\n",
							arg_errors.Value());
					delete rsl;
					return NULL;
				}
			}
			else {
					// In V2 syntax, we convert the ArgList to RSL
				for(int i=0;i<args.Count();i++) {
					if(i) {
						rsl_args += ' ';
					}
					rsl_args += rsl_stringify(args.GetArg(i));
				}
			}
			*rsl += ")(arguments=";
			*rsl += rsl_args;
		}
	}

	// If we're transferring the executable, tell Nordugrid to set the
	// execute bit on the transferred executable.
	if ( transfer_exec ) {
		*rsl += ")(executables=";
		*rsl += condor_basename( executable.c_str() );
	}

	if ( jobAd->LookupString( ATTR_JOB_INPUT, &attr_value ) == 1) {
		// only add to list if not NULL_FILE (i.e. /dev/null)
		if ( ! nullFile(attr_value) ) {
			*rsl += ")(stdin=";
			*rsl += condor_basename(attr_value);
		}
		free( attr_value );
		attr_value = NULL;
	}

	stage_list = buildStageInList();

	if ( stage_list->isEmpty() == false ) {
		char *file;
		stage_list->rewind();

		*rsl += ")(inputfiles=";

		while ( (file = stage_list->next()) != NULL ) {
			*rsl += "(";
			*rsl += condor_basename(file);
			if ( IsUrl( file ) ) {
				formatstr_cat( *rsl, " \"%s\")", file );
			} else {
				*rsl += " \"\")";
			}
		}
	}

	delete stage_list;
	stage_list = NULL;

	if ( jobAd->LookupString( ATTR_JOB_OUTPUT, &attr_value ) == 1) {
		// only add to list if not NULL_FILE (i.e. /dev/null)
		if ( ! nullFile(attr_value) ) {
			*rsl += ")(stdout=" REMOTE_STDOUT_NAME;
		}
		free( attr_value );
		attr_value = NULL;
	}

	if ( jobAd->LookupString( ATTR_JOB_ERROR, &attr_value ) == 1) {
		// only add to list if not NULL_FILE (i.e. /dev/null)
		if ( ! nullFile(attr_value) ) {
			*rsl += ")(stderr=" REMOTE_STDERR_NAME;
		}
		free( attr_value );
	}

	stage_list = buildStageOutList();
	stage_local_list = buildStageOutLocalList( stage_list );

	if ( stage_list->isEmpty() == false ) {
		char *file;
		char *local_file;
		stage_list->rewind();
		stage_local_list->rewind();

		*rsl += ")(outputfiles=";

		while ( (file = stage_list->next()) != NULL ) {
			local_file = stage_local_list->next();
			*rsl += "(";
			*rsl += condor_basename(file);
			if ( IsUrl( local_file ) ) {
				formatstr_cat( *rsl, " \"%s\")", local_file );
			} else {
				*rsl += " \"\")";
			}
		}
	}

	delete stage_list;
	stage_list = NULL;
	delete stage_local_list;
	stage_local_list = NULL;

	*rsl += ')';

	if ( !rsl_suffix.empty() ) {
		*rsl += rsl_suffix;
	}

dprintf(D_FULLDEBUG,"*** RSL='%s'\n",rsl->c_str());
	return rsl;
}