Exemplo n.º 1
0
MyString
MultiLogFiles::loadValueFromSubFile(const MyString &strSubFilename,
		const MyString &directory, const char *keyword)
{
	dprintf( D_FULLDEBUG, "MultiLogFiles::loadValueFromSubFile(%s, %s, %s)\n",
				strSubFilename.Value(), directory.Value(), keyword );

	TmpDir		td;
	if ( directory != "" ) {
		MyString	errMsg;
		if ( !td.Cd2TmpDir(directory.Value(), errMsg) ) {
			dprintf(D_ALWAYS, "Error from Cd2TmpDir: %s\n", errMsg.Value());
			return "";
		}
	}

	StringList	logicalLines;
	if ( fileNameToLogicalLines( strSubFilename, logicalLines ) != "" ) {
		return "";
	}

	MyString	value("");

		// Now look through the submit file logical lines to find the
		// value corresponding to the keyword.
	const char *logicalLine;
	while( (logicalLine = logicalLines.next()) != NULL ) {
		MyString	submitLine(logicalLine);
		MyString	tmpValue = getParamFromSubmitLine(submitLine, keyword);
		if ( tmpValue != "" ) {
			value = tmpValue;
		}
	}

		//
		// Check for macros in the value -- we currently don't
		// handle those.
		//
	if ( value != "" ) {
		if ( strchr(value.Value(), '$') ) {
			dprintf(D_ALWAYS, "MultiLogFiles: macros not allowed "
						"in %s in DAG node submit files\n", keyword);
			value = "";
		}
	}

	if ( directory != "" ) {
		MyString	errMsg;
		if ( !td.Cd2MainDir(errMsg) ) {
			dprintf(D_ALWAYS, "Error from Cd2MainDir: %s\n", errMsg.Value());
			return "";
		}
	}

	return value;
}
Exemplo n.º 2
0
bool writePreSkipEvent( CondorID& condorID, Job* job, const char* DAGNodeName, 
			   const char* directory, const char *logFile )
{
	TmpDir tmpDir;
	MyString	errMsg;
	if ( !tmpDir.Cd2TmpDir( directory, errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to node directory %s: %s\n",
				directory, errMsg.Value() );
		return false;
	}

		// Special HTCondorID for NOOP jobs -- actually indexed by
		// otherwise-unused subprocID.
	condorID._cluster = 0;
	condorID._proc = Job::NOOP_NODE_PROCID;

	condorID._subproc = 1+get_fake_condorID();
		// Increment this value
	set_fake_condorID(condorID._subproc);

	if( job ) {
		job->SetCondorID( condorID );
	}

	WriteUserLog ulog;
	ulog.setEnableGlobalLog( false );
	ulog.setUseXML( false );
	ulog.initialize( std::vector<const char*>(1,logFile), condorID._cluster,
		condorID._proc, condorID._subproc, NULL );

	PreSkipEvent pEvent;
	pEvent.cluster = condorID._cluster;
	pEvent.proc = condorID._proc;
	pEvent.subproc = condorID._subproc;

	MyString pEventNotes("DAG Node: " );
	pEventNotes += DAGNodeName;
		// skipEventLogNotes gets deleted in PreSkipEvent destructor.
	pEvent.skipEventLogNotes = strnewp( pEventNotes.Value() );

	if ( !ulog.writeEvent( &pEvent ) ) {
		EXCEPT( "Error: writing PRESKIP event failed!" );
		return false;
	}
	return true;
}
Exemplo n.º 3
0
    Config&
    configure(Config& cfg, bool writable) const override
    {
        std::string d = mDir.getName();
        std::string getCmd = "cp " + d + "/{0} {1}";
        std::string putCmd = "";
        std::string mkdirCmd = "";

        if (writable)
        {
            putCmd = "cp {0} " + d + "/{1}";
            mkdirCmd = "mkdir -p " + d + "/{0}";
        }

        cfg.HISTORY["test"] =
            std::make_shared<HistoryArchive>("test", getCmd, putCmd, mkdirCmd);
        return cfg;
    }
Exemplo n.º 4
0
//-----------------------------------------------------------------------------
int
Script::BackgroundRun( int reaperId, int dagStatus, int failedCount )
{
	TmpDir		tmpDir;
	MyString	errMsg;
	if ( !tmpDir.Cd2TmpDir( _node->GetDirectory(), errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to node directory %s: %s\n",
				_node->GetDirectory(), errMsg.Value() );

		return 0;
	}

	// Construct the command line, replacing some tokens with
    // information about the job.  All of these values would probably
    // be better inserted into the environment, rather than passed on
    // the command-line... some should be in the job's env as well...

    const char *delimiters = " \t";
    char * token;
	ArgList args;
    char * cmd = strnewp(_cmd);
    for (token = strtok (cmd,  delimiters) ; token != NULL ;
         token = strtok (NULL, delimiters)) {

		MyString arg;

		if ( !strcasecmp( token, "$JOB" ) ) {
			arg += _node->GetJobName();

		} else if ( !strcasecmp( token, "$RETRY" ) ) {
            arg += _node->GetRetries();

		} else if ( !strcasecmp( token, "$MAX_RETRIES" ) ) {
            arg += _node->GetRetryMax();

        } else if ( !strcasecmp( token, "$JOBID" ) ) {
			if ( !_post ) {
				debug_printf( DEBUG_QUIET, "Warning: $JOBID macro should "
							"not be used as a PRE script argument!\n" );
				check_warning_strictness( DAG_STRICT_1 );
				arg += token;
			} else {
            	arg += _node->_CondorID._cluster;
            	arg += '.';
            	arg += _node->_CondorID._proc;
			}

        } else if (!strcasecmp(token, "$RETURN")) {
			if ( !_post ) {
				debug_printf( DEBUG_QUIET, "Warning: $RETURN macro should "
							"not be used as a PRE script argument!\n" );
				check_warning_strictness( DAG_STRICT_1 );
			}
			arg += _retValJob;

		} else if (!strcasecmp( token, "$PRE_SCRIPT_RETURN" ) ) {
			if ( !_post ) {
				debug_printf( DEBUG_QUIET, "Warning: $PRE_SCRIPT_RETURN macro should "
						"not be used as a PRE script argument!\n" );
				check_warning_strictness( DAG_STRICT_1 );
			}
			arg += _retValScript;

		} else if (!strcasecmp(token, "$DAG_STATUS")) {
			arg += dagStatus;

		} else if (!strcasecmp(token, "$FAILED_COUNT")) {
			arg += failedCount;

		} else if (token[0] == '$') {
			// This should probably be a fatal error when -strict is
			// implemented.
			debug_printf( DEBUG_QUIET, "Warning: unrecognized macro %s "
						"in node %s %s script arguments\n", token,
						_node->GetJobName(), _post ? "POST" : "PRE" );
			check_warning_strictness( DAG_STRICT_1 );
			arg += token;
        } else {
			arg += token;
		}

		args.AppendArg(arg.Value());
    }

	_pid = daemonCore->Create_Process( cmd, args,
									   PRIV_UNKNOWN, reaperId, FALSE,
									   NULL, NULL, NULL, NULL, NULL, 0 );
    delete [] cmd;

	if ( !tmpDir.Cd2MainDir( errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to original directory: %s\n",
				errMsg.Value() );
		return 0;
	}

	return _pid;
}
Exemplo n.º 5
0
//-------------------------------------------------------------------------
bool
fake_condor_submit( CondorID& condorID, Job* job, const char* DAGNodeName, 
			   const char* directory, const char *logFile )
{
	TmpDir		tmpDir;
	MyString	errMsg;
	if ( !tmpDir.Cd2TmpDir( directory, errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to node directory %s: %s\n",
				directory, errMsg.Value() );
		return false;
	}

	_subprocID++;
		// Special HTCondorID for NOOP jobs -- actually indexed by
		// otherwise-unused subprocID.
	condorID._cluster = 0;
	condorID._proc = Job::NOOP_NODE_PROCID;
	condorID._subproc = _subprocID;

		// Make sure that this job gets marked as a NOOP 
	if( job ) {
		job->SetCondorID( condorID );
	}

	WriteUserLog ulog;
	ulog.setEnableGlobalLog( false );
	ulog.setUseXML( false );
	ulog.initialize( logFile, condorID._cluster,
		condorID._proc, condorID._subproc, NULL );

	SubmitEvent subEvent;
	subEvent.cluster = condorID._cluster;
	subEvent.proc = condorID._proc;
	subEvent.subproc = condorID._subproc;

		// We need some value for submitHost for the event to be read
		// correctly.
	subEvent.setSubmitHost( "<dummy-submit-for-noop-job>" );

	MyString subEventNotes("DAG Node: " );
	subEventNotes += DAGNodeName;
		// submitEventLogNotes get deleted in SubmitEvent destructor.
	subEvent.submitEventLogNotes = strnewp( subEventNotes.Value() );

	if ( !ulog.writeEvent( &subEvent ) ) {
		EXCEPT( "Error: writing dummy submit event for NOOP node failed!" );
		return false;
	}


	JobTerminatedEvent termEvent;
	termEvent.cluster = condorID._cluster;
	termEvent.proc = condorID._proc;
	termEvent.subproc = condorID._subproc;
	termEvent.normal = true;
	termEvent.returnValue = 0;
	termEvent.signalNumber = 0;

	if ( !ulog.writeEvent( &termEvent ) ) {
		EXCEPT( "Error: writing dummy terminated event for NOOP node failed!" );
		return false;
	}

	return true;
}
Exemplo n.º 6
0
//-------------------------------------------------------------------------
bool
condor_submit( const Dagman &dm, const char* cmdFile, CondorID& condorID,
			   const char* DAGNodeName, MyString &DAGParentNodeNames,
			   List<Job::NodeVar> *vars, int retry,
			   const char* directory, const char *workflowLogFile,
			   bool hold_claim )
{
	TmpDir		tmpDir;
	MyString	errMsg;
	if ( !tmpDir.Cd2TmpDir( directory, errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to node directory %s: %s\n",
				directory, errMsg.Value() );
		return false;
	}

	ArgList args;

	// construct arguments to condor_submit to add attributes to the
	// job classad which identify the job's node name in the DAG, the
	// node names of its parents in the DAG, and the job ID of DAGMan
	// itself; then, define submit_event_notes to print the job's node
	// name inside the submit event in the userlog

	// NOTE: we specify the job ID of DAGMan using only its cluster ID
	// so that it may be referenced by jobs in their priority
	// attribute (which needs an int, not a string).  Doing so allows
	// users to effectively "batch" jobs by DAG so that when they
	// submit many DAGs to the same schedd, all the ready jobs from
	// one DAG complete before any jobs from another begin.

	args.AppendArg( dm.condorSubmitExe );

	args.AppendArg( "-a" );
	MyString nodeName = MyString(ATTR_DAG_NODE_NAME_ALT) + " = " + DAGNodeName;
	args.AppendArg( nodeName.Value() );

		// append a line adding the parent DAGMan's cluster ID to the job ad
	args.AppendArg( "-a" );
	MyString dagJobId = MyString( "+" ) + ATTR_DAGMAN_JOB_ID + " = " +
				dm.DAGManJobId._cluster;
	args.AppendArg( dagJobId.Value() );

		// now we append a line setting the same thing as a submit-file macro
		// (this is necessary so the user can reference it in the priority)
	args.AppendArg( "-a" );
	MyString dagJobIdMacro = MyString( "" ) + ATTR_DAGMAN_JOB_ID + " = " +
				dm.DAGManJobId._cluster;
	args.AppendArg( dagJobIdMacro.Value() );

	args.AppendArg( "-a" );
	MyString submitEventNotes = MyString(
				"submit_event_notes = DAG Node: " ) + DAGNodeName;
	args.AppendArg( submitEventNotes.Value() );

	ASSERT( workflowLogFile );

		// We need to append the DAGman default log file to
		// the log file list
	args.AppendArg( "-a" );
	std::string dlog( "dagman_log = " );
	dlog += workflowLogFile;
	args.AppendArg( dlog.c_str() );
	debug_printf( DEBUG_VERBOSE, "Adding a DAGMan workflow log %s\n",
				workflowLogFile );

		// Now append the mask
	debug_printf( DEBUG_VERBOSE, "Masking the events recorded in the DAGMAN workflow log\n" );
	args.AppendArg( "-a" );
	std::string dmask("+");
	dmask += ATTR_DAGMAN_WORKFLOW_MASK;
	dmask += " = \"";
	const char *eventMask = getEventMask();
	debug_printf( DEBUG_VERBOSE, "Mask for workflow log is %s\n",
				eventMask );
	dmask += eventMask;
	dmask += "\"";
	args.AppendArg( dmask.c_str() );

		// Suppress the job's log file if that option is enabled.
	if ( dm._suppressJobLogs ) {
		debug_printf( DEBUG_VERBOSE, "Suppressing node job log file\n" );
		args.AppendArg( "-a" );
		args.AppendArg( "log = ''" );
	}

	ArgList parentNameArgs;
	parentNameArgs.AppendArg( "-a" );
	MyString parentNodeNames = MyString( "+DAGParentNodeNames = " ) +
	                        "\"" + DAGParentNodeNames + "\"";
	parentNameArgs.AppendArg( parentNodeNames.Value() );

		// set any VARS specified in the DAG file
	MyString anotherLine;
	ListIterator<Job::NodeVar> varsIter(*vars);
	Job::NodeVar nodeVar;
	while ( varsIter.Next(nodeVar) ) {

			// Substitute the node retry count if necessary.  Note that
			// we can't do this in Job::ResolveVarsInterpolations()
			// because that's only called at parse time.
		MyString value = nodeVar._value;
		MyString retryStr( retry );
		value.replaceString( "$(RETRY)", retryStr.Value() );
		MyString varStr = nodeVar._name + " = " + value;

		args.AppendArg( "-a" );
		args.AppendArg( varStr.Value() );
	}

		// Set the special DAG_STATUS variable (mainly for use by
		// "final" nodes).
	args.AppendArg( "-a" );
	MyString var = "DAG_STATUS = ";
	var += dm.dag->_dagStatus;
	args.AppendArg( var.Value() );

		// Set the special FAILED_COUNT variable (mainly for use by
		// "final" nodes).
	args.AppendArg( "-a" );
	var = "FAILED_COUNT = ";
	var += dm.dag->NumNodesFailed();
	args.AppendArg( var.Value() );

		// how big is the command line so far
	MyString display;
	args.GetArgsStringForDisplay( &display );
	int cmdLineSize = display.Length();

	parentNameArgs.GetArgsStringForDisplay( &display );
	int DAGParentNodeNamesLen = display.Length();
		// how many additional chars must we still add to command line
	        // NOTE: according to the POSIX spec, the args +
   	        // environ given to exec() cannot exceed
   	        // _POSIX_ARG_MAX, so we also need to calculate & add
   	        // the size of environ** to reserveNeeded
	int reserveNeeded = strlen( cmdFile );
	int maxCmdLine = _POSIX_ARG_MAX;

		// if we don't have room for DAGParentNodeNames, leave it unset
	if( cmdLineSize + reserveNeeded + DAGParentNodeNamesLen > maxCmdLine ) {
		debug_printf( DEBUG_NORMAL, "Warning: node %s has too many parents "
					  "to list in its classad; leaving its DAGParentNodeNames "
					  "attribute undefined\n", DAGNodeName );
		check_warning_strictness( DAG_STRICT_3 );
	} else {
		args.AppendArgsFromArgList( parentNameArgs );
	}

	if( hold_claim ){
		args.AppendArg( "-a" );
		MyString holdit = MyString("+") + MyString(ATTR_JOB_KEEP_CLAIM_IDLE) + " = "
			+ dm._claim_hold_time;
		args.AppendArg( holdit.Value() );	
	}
	
	if (dm._submitDagDeepOpts.suppress_notification) {
		args.AppendArg( "-a" );
		MyString notify = MyString("notification = never");
		args.AppendArg( notify.Value() );
	}

	args.AppendArg( cmdFile );

	bool success = do_submit( args, condorID, dm.prohibitMultiJobs );

	if ( !tmpDir.Cd2MainDir( errMsg ) ) {
		debug_printf( DEBUG_QUIET,
				"Could not change to original directory: %s\n",
				errMsg.Value() );
		success = false;
	}

	return success;
}
Exemplo n.º 7
0
//-------------------------------------------------------------------------
bool
GetConfigAndAttrs( /* const */ StringList &dagFiles, bool useDagDir, 
			MyString &configFile, StringList &attrLines, MyString &errMsg )
{
	bool		result = true;

		// Note: destructor will change back to original directory.
	TmpDir		dagDir;

	dagFiles.rewind();
	char *dagFile;
	while ( (dagFile = dagFiles.next()) != NULL ) {

			//
			// Change to the DAG file's directory if necessary, and
			// get the filename we need to use for it from that directory.
			//
		const char *	newDagFile;
		if ( useDagDir ) {
			MyString	tmpErrMsg;
			if ( !dagDir.Cd2TmpDirFile( dagFile, tmpErrMsg ) ) {
				AppendError( errMsg,
						MyString("Unable to change to DAG directory ") +
						tmpErrMsg );
				return false;
			}
			newDagFile = condor_basename( dagFile );
		} else {
			newDagFile = dagFile;
		}

		StringList		configFiles;

			// Note: destructor will close file.
		MultiLogFiles::FileReader reader;
		errMsg = reader.Open( newDagFile );
		if ( errMsg != "" ) {
			return false;
		}

		MyString logicalLine;
		while ( reader.NextLogicalLine( logicalLine ) ) {
			if ( logicalLine != "" ) {
					// Note: StringList constructor removes leading
					// whitespace from lines.
				StringList tokens( logicalLine.Value(), " \t" );
				tokens.rewind();

				const char *firstToken = tokens.next();
				if ( !strcasecmp( firstToken, "config" ) ) {

						// Get the value.
					const char *newValue = tokens.next();
					if ( !newValue || !strcmp( newValue, "" ) ) {
						AppendError( errMsg, "Improperly-formatted "
									"file: value missing after keyword "
									"CONFIG" );
			    		result = false;
					} else {

							// Add the value we just found to the config
							// files list (if it's not already in the
							// list -- we don't want duplicates).
						configFiles.rewind();
						char *existingValue;
						bool alreadyInList = false;
						while ( ( existingValue = configFiles.next() ) ) {
							if ( !strcmp( existingValue, newValue ) ) {
								alreadyInList = true;
							}
						}

						if ( !alreadyInList ) {
								// Note: append copies the string here.
							configFiles.append( newValue );
						}
					}

					//some DAG commands are needed for condor_submit_dag, too...
				} else if ( !strcasecmp( firstToken, "SET_JOB_ATTR" ) ) {
						// Strip of DAGMan-specific command name; the
						// rest we pass to the submit file.
					logicalLine.replaceString( "SET_JOB_ATTR", "" );
					logicalLine.trim();
					if ( logicalLine == "" ) {
						AppendError( errMsg, "Improperly-formatted "
									"file: value missing after keyword "
									"SET_JOB_ATTR" );
						result = false;
					} else {
						attrLines.append( logicalLine.Value() );
					}
				}
			}
		}
	
		reader.Close();

			//
			// Check the specified config file(s) against whatever we
			// currently have, setting the config file if it hasn't
			// been set yet, flagging an error if config files conflict.
			//
		configFiles.rewind();
		char *		cfgFile;
		while ( (cfgFile = configFiles.next()) ) {
			MyString	cfgFileMS = cfgFile;
			MyString	tmpErrMsg;
			if ( MakePathAbsolute( cfgFileMS, tmpErrMsg ) ) {
				if ( configFile == "" ) {
					configFile = cfgFileMS;
				} else if ( configFile != cfgFileMS ) {
					AppendError( errMsg, MyString("Conflicting DAGMan ") +
								"config files specified: " + configFile +
								" and " + cfgFileMS );
					result = false;
				}
			} else {
				AppendError( errMsg, tmpErrMsg );
				result = false;
			}
		}

			//
			// Go back to our original directory.
			//
		MyString	tmpErrMsg;
		if ( !dagDir.Cd2MainDir( tmpErrMsg ) ) {
			AppendError( errMsg,
					MyString("Unable to change to original directory ") +
					tmpErrMsg );
			result = false;
		}
	}

	return result;
}
Exemplo n.º 8
0
//---------------------------------------------------------------------------
int
runSubmitDag( const SubmitDagDeepOptions &deepOpts,
			const char *dagFile, const char *directory, int priority,
			bool isRetry )
{
	int result = 0;

		// Change to the appropriate directory if necessary.
	TmpDir tmpDir;
	MyString errMsg;
	if ( directory ) {
		if ( !tmpDir.Cd2TmpDir( directory, errMsg ) ) {
			fprintf( stderr, "Error (%s) changing to node directory\n",
						errMsg.Value() );
			result = 1;
			return result;
		}
	}

		// Build up the command line for the recursive run of
		// condor_submit_dag.  We need -no_submit so we don't
		// actually run the subdag now; we need -update_submit
		// so the lower-level .condor.sub file will get
		// updated, in case it came from an earlier version
		// of condor_submit_dag.
	ArgList args;
	args.AppendArg( "condor_submit_dag" );
	args.AppendArg( "-no_submit" );
	args.AppendArg( "-update_submit" );

		// Add in arguments we're passing along.
	if ( deepOpts.bVerbose ) {
		args.AppendArg( "-verbose" );
	}

	if ( deepOpts.bForce && !isRetry ) {
		args.AppendArg( "-force" );
	}

	if (deepOpts.strNotification != "" ) {
		args.AppendArg( "-notification" );
		if(deepOpts.suppress_notification) {
			args.AppendArg( "never" );
		} else { 
			args.AppendArg( deepOpts.strNotification.Value() );
		}
	}

	if ( deepOpts.strDagmanPath != "" ) {
		args.AppendArg( "-dagman" );
		args.AppendArg( deepOpts.strDagmanPath.Value() );
	}

	if ( deepOpts.useDagDir ) {
		args.AppendArg( "-usedagdir" );
	}

	if ( deepOpts.strOutfileDir != "" ) {
		args.AppendArg( "-outfile_dir" );
		args.AppendArg( deepOpts.strOutfileDir.Value() );
	}

	args.AppendArg( "-autorescue" );
	args.AppendArg( deepOpts.autoRescue );

	if ( deepOpts.doRescueFrom != 0 ) {
		args.AppendArg( "-dorescuefrom" );
		args.AppendArg( deepOpts.doRescueFrom );
	}

	if ( deepOpts.allowVerMismatch ) {
		args.AppendArg( "-allowver" );
	}

	if ( deepOpts.importEnv ) {
		args.AppendArg( "-import_env" );
	}

	if ( deepOpts.recurse ) {
		args.AppendArg( "-do_recurse" );
	}

	if ( deepOpts.updateSubmit ) {
		args.AppendArg( "-update_submit" );
	}

	if( priority != 0) {
		args.AppendArg( "-Priority" );
		args.AppendArg( priority );
	}

	if( deepOpts.suppress_notification ) {
		args.AppendArg( "-suppress_notification" );
	} else {
		args.AppendArg( "-dont_suppress_notification" );
	}

	args.AppendArg( dagFile );

	MyString cmdLine;
	args.GetArgsStringForDisplay( &cmdLine );
	dprintf( D_ALWAYS, "Recursive submit command: <%s>\n",
				cmdLine.Value() );

		// Now actually run the command.
	int retval = my_system( args );
	if ( retval != 0 ) {
		dprintf( D_ALWAYS, "ERROR: condor_submit_dag -no_submit "
					"failed on DAG file %s.\n", dagFile );
		result = 1;
	}

		// Change back to the directory we started from.
	if ( !tmpDir.Cd2MainDir( errMsg ) ) {
		dprintf( D_ALWAYS, "Error (%s) changing back to original directory\n",
					errMsg.Value() );
	}

	return result;
}
Exemplo n.º 9
0
///////////////////////////////////////////////////////////////////////////////
// Note: this method should get speeded up (see Gnats PR 846).
MyString
MultiLogFiles::loadLogFileNameFromSubFile(const MyString &strSubFilename,
		const MyString &directory, bool &isXml, bool usingDefaultNode)
{
	dprintf( D_FULLDEBUG, "MultiLogFiles::loadLogFileNameFromSubFile(%s, %s)\n",
				strSubFilename.Value(), directory.Value() );

	TmpDir		td;
	if ( directory != "" ) {
		MyString	errMsg;
		if ( !td.Cd2TmpDir(directory.Value(), errMsg) ) {
			dprintf(D_ALWAYS, "Error from Cd2TmpDir: %s\n", errMsg.Value());
			return "";
		}
	}

	StringList	logicalLines;
	if ( fileNameToLogicalLines( strSubFilename, logicalLines ) != "" ) {
		return "";
	}

	MyString	logFileName("");
	MyString	initialDir("");
	MyString	isXmlLogStr("");

		// Now look through the submit file logical lines to find the
		// log file and initial directory (if specified) and combine
		// them into a path to the log file that's either absolute or
		// relative to the DAG submit directory.  Also look for log_xml.
	const char *logicalLine;
	while( (logicalLine = logicalLines.next()) != NULL ) {
		MyString	submitLine(logicalLine);
		MyString	tmpLogName = getParamFromSubmitLine(submitLine, "log");
		if ( tmpLogName != "" ) {
			logFileName = tmpLogName;
		}

			// If we are using the default node log, we don't care
			// about these
		if( !usingDefaultNode ) {
			MyString	tmpInitialDir = getParamFromSubmitLine(submitLine,
					"initialdir");
			if ( tmpInitialDir != "" ) {
				initialDir = tmpInitialDir;
			}

			MyString tmpLogXml = getParamFromSubmitLine(submitLine, "log_xml");
			if ( tmpLogXml != "" ) {
				isXmlLogStr = tmpLogXml;
			}
		}
	}

	if ( !usingDefaultNode ) {
			//
			// Check for macros in the log file name -- we currently don't
			// handle those.
			//
			// If we are using the default node, we don't need to check this
		if ( logFileName != "" ) {
			if ( strstr(logFileName.Value(), "$(") ) {
				dprintf(D_ALWAYS, "MultiLogFiles: macros ('$(...') not allowed "
						"in log file name (%s) in DAG node submit files\n",
						logFileName.Value());
				logFileName = "";
			}
		}

			// Do not need to prepend initialdir if we are using the 
			// default node log
		if ( logFileName != "" ) {
				// Prepend initialdir to log file name if log file name is not
				// an absolute path.
			if ( initialDir != "" && !fullpath(logFileName.Value()) ) {
				logFileName = initialDir + DIR_DELIM_STRING + logFileName;
			}

				// We do this in case the same log file is specified with a
				// relative and an absolute path.  
				// Note: we now do further checking that doesn't rely on
				// comparing paths to the log files.  wenger 2004-05-27.
			CondorError errstack;
			if ( !makePathAbsolute( logFileName, errstack ) ) {
				dprintf(D_ALWAYS, "%s\n", errstack.getFullText().c_str());
				return "";
			}
		}
		isXmlLogStr.lower_case();
		isXml = (isXmlLogStr == "true");
		if ( directory != "" ) {
			MyString	errMsg;
			if ( !td.Cd2MainDir(errMsg) ) {
				dprintf(D_ALWAYS, "Error from Cd2MainDir: %s\n", errMsg.Value());
				return "";
			}
		}
	}
	return logFileName;
}
Exemplo n.º 10
0
 std::string
 getArchiveDirName() const override
 {
     return mDir.getName();
 }
Exemplo n.º 11
0
/* Helper function: write the input files mime encode in the inputAd into iwd */
bool
write_input_files(const ClassAd* inputAd, const char *iwd)
{
	bool return_value = true;
	char *file_name, *file_data;
	unsigned char *output;
	char buf[60];
	int i, output_length, fd;
	int flags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_LARGEFILE;

	TmpDir tmpdir;
	MyString tmpdir_error;
	if (tmpdir.Cd2TmpDir(iwd,tmpdir_error) == false ) {
		// We failed to cd to our iwd.  This should NEVER happen.
		EXCEPT("write_input_files iwd failure: %s",tmpdir_error.Value());
	}

	i=0; file_name=NULL; file_data=NULL;output=NULL;
	while (return_value==true) {	// keep looping until break or failure
		i++;
		sprintf(buf,"INPUT_FILE_NAME_%d",i);
		inputAd->LookupString(buf,&file_name);
		if (!file_name) break;		// no more files
		sprintf(buf,"INPUT_FILE_DATA_%d",i);
		inputAd->LookupString(buf,&file_data);
		if ( file_data ) {
			// Caller needs to free *output if non-NULL
			condor_base64_decode(file_data,&output,&output_length);
			if ( output ) {
				fd = safe_open_wrapper_follow( condor_basename(file_name), flags, 0666 );
				if ( fd > -1 ) {
					write(fd,output,output_length);
					close(fd);
					dprintf(D_FULLDEBUG,"Wrote %d bytes to file %s%c%s\n",
								output_length, iwd, DIR_DELIM_CHAR, 
								condor_basename(file_name));
				} else {
					return_value = false;
				}
				free(output);
				output = NULL;
			} else {
				dprintf(D_ALWAYS,"Failed to decode base64 in attribute %s for file %s\n",
						buf,condor_basename(file_name));
				return_value = false;
			}
			free(file_data);
			file_data = NULL;
		} else {
			// INPUT_FILE_NAME specified, but no data... so just touch the file
			fd = safe_open_wrapper_follow( condor_basename(file_name), flags, 0666 );
			if ( fd > -1 ) {
				close(fd);
				dprintf(D_FULLDEBUG,"Wrote empty file %s%c%s\n",
								iwd, DIR_DELIM_CHAR, 
								condor_basename(file_name));
			}
		}
		free(file_name);
		file_name = NULL;
	}

	if ( return_value ) {
		dprintf(D_ALWAYS,"Wrote %d files to subdir %s\n",i-1,iwd);
	} else {
		dprintf(D_ALWAYS,"Failed to write file %d to subdir %s\n",i,iwd);
	}
		
	return return_value;
}