Index: trunk/pbs_drmaa/submit.c
===================================================================
--- trunk/pbs_drmaa/submit.c	(revision 99)
+++ trunk/pbs_drmaa/submit.c	(revision 1)
@@ -1,3 +1,3 @@
-/* $Id$ */
+/* $Id: submit.c 386 2011-01-06 18:13:33Z mamonski $ */
 /*
  *  FedStage DRMAA for PBS Pro
@@ -24,5 +24,4 @@
 #include <unistd.h>
 #include <string.h>
-#include <stdlib.h>
 
 #include <pbs_ifl.h>
@@ -30,5 +29,4 @@
 
 #include <drmaa_utils/conf.h>
-#include <drmaa_utils/exec.h>
 #include <drmaa_utils/drmaa.h>
 #include <drmaa_utils/drmaa_util.h>
@@ -48,17 +46,20 @@
 		__attribute__ ((unused))
 #	endif
-	= "$Id$";
+	= "$Id: submit.c 386 2011-01-06 18:13:33Z mamonski $";
 #endif
 
-static void pbsdrmaa_submit_destroy( pbsdrmaa_submit_t *self );
-
-static char *pbsdrmaa_submit_submit( pbsdrmaa_submit_t *self );
-
-static void pbsdrmaa_submit_eval( pbsdrmaa_submit_t *self );
-
-static void pbsdrmaa_submit_set( pbsdrmaa_submit_t *self, const char *pbs_attr, char *value, unsigned placeholders );
-
-static struct attrl *pbsdrmaa_submit_filter(struct attrl *pbs_attr);
-
+static void
+pbsdrmaa_submit_destroy( pbsdrmaa_submit_t *self );
+
+static char *
+pbsdrmaa_submit_submit( pbsdrmaa_submit_t *self );
+
+static void
+pbsdrmaa_submit_eval( pbsdrmaa_submit_t *self );
+
+
+static void
+pbsdrmaa_submit_set( pbsdrmaa_submit_t *self, const char *pbs_attr,
+		char *value, unsigned placeholders );
 
 static void pbsdrmaa_submit_apply_defaults( pbsdrmaa_submit_t *self );
@@ -100,5 +101,6 @@
 		self->apply_job_environment = pbsdrmaa_submit_apply_job_environment;
 		self->apply_email_notification = pbsdrmaa_submit_apply_email_notification;
-		self->apply_native_specification = pbsdrmaa_submit_apply_native_specification;
+		self->apply_native_specification =
+			pbsdrmaa_submit_apply_native_specification;
 
 		self->pbs_job_attributes = pbsdrmaa_pbs_template_new();
@@ -136,75 +138,63 @@
 pbsdrmaa_submit_submit( pbsdrmaa_submit_t *self )
 {
+	volatile bool conn_lock = false;
 	struct attrl *volatile pbs_attr = NULL;
 	char *volatile job_id = NULL;
 	TRY
 	 {
-		fsd_template_t *pbs_tmpl = self->pbs_job_attributes;
-		int i;
-
-		for( i = PBSDRMAA_N_PBS_ATTRIBUTES - 1; i >= 0; i-- ) /* down loop -> start with custom resources */
+		const fsd_template_t *pbs_tmpl = self->pbs_job_attributes;
+		unsigned i;
+
+		for( i = 0;  i < PBSDRMAA_N_PBS_ATTRIBUTES;  i++ )
 		 {
 			const char *name = pbs_tmpl->by_code( pbs_tmpl, i )->name;
-			const char *value = pbs_tmpl->get_attr( pbs_tmpl, name );
-
-			if (!value)
-				continue;
-
-			if ( i == PBSDRMAA_ATTR_CUSTOM_RESOURCES)
+			if( name  &&  name[0] != '!' && pbs_tmpl->get_attr( pbs_tmpl, name ) )
 			 {
-				char *value_copy = fsd_strdup(value);
-				char *tok_comma_ctx = NULL;
-				char *res_token = NULL;
-				/* matlab:2,simulink:1 */
-
-				for (res_token = strtok_r(value_copy, ";", &tok_comma_ctx); res_token; res_token = strtok_r(NULL, ";", &tok_comma_ctx))
+				struct attrl *p;
+				const char *resource;
+				const char *value;
+				value = pbs_tmpl->get_attr( pbs_tmpl, name );
+				fsd_malloc( p, struct attrl );
+				memset( p, 0, sizeof(struct attrl) );
+				p->next = pbs_attr;
+				pbs_attr = p;
+				resource = strchr( name, '.' );
+				if( resource )
 				 {
-					char *value_p = strstr(res_token, ":");
-
-					if (value_p)
-					 {
-						char *name_p = NULL;
-						*value_p = '\0';
-						value_p++;
-						name_p = fsd_asprintf("Resource_List.%s",res_token);
-						pbs_attr = pbsdrmaa_add_attr( pbs_attr, name_p, value_p );
-						fsd_free(name_p);
-					 }
-					else
-					 {
-						fsd_exc_raise_code( FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE );
-					 }
-				 }
-
-				fsd_free(value_copy);
-			 }
-			else if (i == PBSDRMAA_ATTR_NODE_PROPERTIES)
-			 {
-				const char *nodes_value = pbs_tmpl->get_attr( pbs_tmpl, PBSDRMAA_NODES );
-				char *final_value = NULL;
-
-				if (nodes_value)
-				 {
-					final_value = fsd_asprintf("%s:%s",nodes_value, value);
+					p->name = fsd_strndup( name, resource-name );
+					p->resource = fsd_strdup( resource+1 );
 				 }
 				else
-				 {
-					final_value = fsd_asprintf("1:%s", value);
-				 }
-
-				pbs_tmpl->set_attr( pbs_tmpl, PBSDRMAA_NODES, final_value);
-				fsd_free(final_value);
+					p->name = fsd_strdup( name );
+				fsd_log_debug(("set attr: %s = %s", name, value));
+				p->value = fsd_strdup( value );
+				p->op = SET;
+			 }
+		 }
+
+		conn_lock = fsd_mutex_lock( &self->session->drm_connection_mutex );
+retry:
+		job_id = pbs_submit( ((pbsdrmaa_session_t*)self->session)->pbs_conn,
+				(struct attropl*)pbs_attr, self->script_filename,
+				self->destination_queue, NULL );
+		if( job_id == NULL )
+		{
+			if (pbs_errno == PBSE_PROTOCOL || pbs_errno == PBSE_EXPIRED)
+			 {
+				pbsdrmaa_session_t *pbsself = (pbsdrmaa_session_t*)self->session;
+				pbs_disconnect( pbsself->pbs_conn );
+				sleep(1);
+				pbsself->pbs_conn = pbs_connect( pbsself->super.contact );
+				if( pbsself->pbs_conn < 0 )
+					pbsdrmaa_exc_raise_pbs( "pbs_connect" );
+				else
+					goto retry;
 			 }
 			else
 			 {
-				pbs_attr = pbsdrmaa_add_attr( pbs_attr, name, value );
+				pbsdrmaa_exc_raise_pbs( "pbs_submit" );
 			 }
-		 }
-
-
-		pbs_attr = pbsdrmaa_submit_filter(pbs_attr);
-
-		job_id = ((pbsdrmaa_session_t *)self->session)->pbs_connection->submit( ((pbsdrmaa_session_t *)self->session)->pbs_connection, (struct attropl*)pbs_attr, self->script_filename, self->destination_queue);
-
+		}
+		conn_lock = fsd_mutex_unlock( &self->session->drm_connection_mutex );
 	 }
 	EXCEPT_DEFAULT
@@ -215,4 +205,6 @@
 	FINALLY
 	 {
+		if( conn_lock )
+			conn_lock = fsd_mutex_unlock( &self->session->drm_connection_mutex );
 		if( pbs_attr )
 			pbsdrmaa_free_attrl( pbs_attr );
@@ -309,6 +301,5 @@
 		if( wd != NULL )
 			script_len += strlen("cd ") + strlen(wd) + strlen("; ");
-		script_len += strlen("touch ") + strlen(((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix) + strlen("/$PBS_JOBID.started;");
-		script_len += strlen(executable);
+		script_len += strlen("exec ") + strlen(executable);
 		if( argv != NULL )
 			for( i = argv;  *i != NULL;  i++ )
@@ -316,6 +307,4 @@
 		if( input_path != NULL )
 			script_len += strlen(" <") + strlen(input_path);
-
-		script_len += strlen(";EXIT_CODE=$?; echo $EXIT_CODE >") + strlen(((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix) + strlen("/$PBS_JOBID.exitcode; exit $EXIT_CODE");
 	 }
 
@@ -327,6 +316,5 @@
 		if( wd != NULL )
 			s += sprintf( s, "cd %s; ", wd );
-		s += sprintf( s, "touch %s/$PBS_JOBID.started;", ((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix);
-		s += sprintf( s, "%s", executable );
+		s += sprintf( s, "exec %s", executable );
 		if( argv != NULL )
 			for( i = argv;  *i != NULL;  i++ )
@@ -334,7 +322,4 @@
 		if( input_path != NULL )
 			s += sprintf( s, " <%s", input_path );
-
-		s += sprintf( s, ";EXIT_CODE=$?; echo $EXIT_CODE >%s/$PBS_JOBID.exitcode; exit $EXIT_CODE", ((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix);
-
 		fsd_assert( s == script+script_len );
 	 }
@@ -407,4 +392,5 @@
 	fsd_template_t *pbs_attr = self->pbs_job_attributes;
 	const char *join_files;
+	bool b_join_files;
 	int i;
 
@@ -436,13 +422,6 @@
 
 	join_files = jt->get_attr( jt, DRMAA_JOIN_FILES );
-	if (join_files != NULL && strcmp(join_files, "y") == 0)
-	  {
-		pbs_attr->set_attr( pbs_attr, PBSDRMAA_JOIN_FILES, "oe" ); 
-	  }
-        else if (join_files != NULL && strcmp(join_files, "n") != 0)
-          {
-		fsd_exc_raise_fmt( FSD_ERRNO_INVALID_VALUE, "invalid value of %s attribute. Should be 'y' or 'n'.",
-					DRMAA_JOIN_FILES );
-          }
+	b_join_files = join_files != NULL  &&  !strcmp(join_files,"1");
+	pbs_attr->set_attr( pbs_attr, PBSDRMAA_JOIN_FILES, (b_join_files ? "y" : "n") ); 
 }
 
@@ -474,6 +453,4 @@
 }
 
-
-
 void
 pbsdrmaa_submit_apply_job_environment( pbsdrmaa_submit_t *self )
@@ -481,38 +458,21 @@
 	const fsd_template_t *jt = self->job_template;
 	const char *const *env_v;
-	const char *jt_wd;
-	char *wd;
-	char *env_c = NULL;
-	int ii = 0, len = 0;
 
 	env_v = jt->get_v_attr( jt, DRMAA_V_ENV);
-	jt_wd    = jt->get_attr( jt, DRMAA_WD );
-	
-	if (!jt_wd)
+
+	if (env_v)
 	{
-		wd = fsd_getcwd();
-	}
-	else
-	{
-		wd = fsd_strdup(jt_wd);
-	}
-
-	if (env_v)
-	 {
+		char *env_c = NULL;
+		int ii = 0, len = 0;
+
 		ii = 0;
-		while (env_v[ii])
-		 {
+		while (env_v[ii]) {
 			len += strlen(env_v[ii]) + 1;
 			ii++;
-		 }
-	 }
-	
-	len+= strlen("PBS_O_WORKDIR=") + strlen(wd);
-
-	fsd_calloc(env_c, len + 1, char);
-	env_c[0] = '\0';
-
-	if (env_v)
-	{
+		}
+
+		fsd_calloc(env_c, len + 1, char);
+		env_c[0] = '\0';
+
 		ii = 0;
 		while (env_v[ii]) {
@@ -522,13 +482,10 @@
 		}
 
+		env_c[strlen(env_c) -1 ] = '\0'; /*remove the last ',' */
+
+		self->pbs_job_attributes->set_attr(self->pbs_job_attributes, "Variable_List", env_c);
+
+		fsd_free(env_c);
 	}
-	
-	strcat(env_c, "PBS_O_WORKDIR=");
-	strcat(env_c, wd);
-
-	self->pbs_job_attributes->set_attr(self->pbs_job_attributes, "Variable_List", env_c);
-
-	fsd_free(env_c);
-	fsd_free(wd);
 }
 
@@ -560,24 +517,5 @@
 }
 
-static const char *get_job_env(pbsdrmaa_submit_t *self, const char *env_name)
-{
-	const fsd_template_t *jt = self->job_template;
-	const char *const *env_v = jt->get_v_attr( jt, DRMAA_V_ENV);
-	int ii = 0;
-
-	while (env_v[ii])
-	 {
-		char *eq_p = strstr(env_v[ii], "=");
-
-		if ((eq_p) && (strncmp(env_v[ii], env_name, eq_p - env_v[ii]) == 0))
-				return ++eq_p;
-
-		ii++;
-	 }
-
-	return NULL;
-}
-
-static void parse_resources(pbsdrmaa_submit_t *self, fsd_template_t *pbs_attr,const char *resources)
+static void parse_resources(fsd_template_t *pbs_attr,const char *resources)
 {
 	char * volatile name = NULL;
@@ -598,8 +536,5 @@
 				name = fsd_asprintf("Resource_List.%s", arg);
 				value = ++psep;
-				if (value[0] == '$' && get_job_env(self, value + 1))
-					pbs_attr->set_attr( pbs_attr, name , get_job_env(self, value + 1) ); /*get value from job env variable */
-				else
-					pbs_attr->set_attr( pbs_attr, name , value );
+				pbs_attr->set_attr( pbs_attr, name , value );
 				fsd_free(name);
 				name = NULL;
@@ -607,5 +542,6 @@
 			else
 			{
-				fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE, "Invalid native specification: %s (Invalid resource specification: %s)", resources, arg);
+                                fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE, "Invalid native specification: %s (Invalid resource specification: %s)", resources, arg);
+
 			}
 		}
@@ -629,5 +565,5 @@
 	TRY
 	  {
-		for (arg = strtok_r(add_attr_copy, ",", &ctxt); arg; arg = strtok_r(NULL, ",",&ctxt) )
+		for (arg = strtok_r(add_attr_copy, ",", &ctxt); arg; arg = strtok_r(NULL, ":",&ctxt) )
 		{
 			name = fsd_strdup(strtok_r(arg, "=", &ctxt2));
@@ -651,6 +587,4 @@
 		const char *native_specification )
 {
-	fsd_log_enter(( "({native_specification=%s})", native_specification ));
-
 	if( native_specification == NULL )
 		native_specification = self->job_template->get_attr(
@@ -660,4 +594,5 @@
 
 	{
+		fsd_iter_t * volatile args_list = fsd_iter_new(NULL, 0);
 		fsd_template_t *pbs_attr = self->pbs_job_attributes;
 		char *arg = NULL;
@@ -667,29 +602,19 @@
 
 		TRY
-		  {
-			for (arg = strtok_r((char *)native_spec_copy, " \t", &ctxt); arg; arg = strtok_r(NULL, " \t",&ctxt) ) {
-				if (!opt)
-				  {
-					if ( (arg[0] != '-') || (strlen(arg) != 2) )
+		 {
+			for (arg = strtok_r(native_spec_copy, " \t", &ctxt); arg; arg = strtok_r(NULL, " \t",&ctxt) ) {
+				if (!opt) {
+					if ( (arg[0] != '-') || ((strlen(arg) != 2) &&  arg[2] != ' ' && arg[1] !='-' ) )
 						fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE,
-							"Invalid native specification: -o(ption) expected (arg=%s native=%s).",
-							arg, native_specification);
-
-					opt = arg[1];
-
-					/* handle NO-arg options */
-
-					switch (opt) {
-						case 'h' :
-							pbs_attr->set_attr( pbs_attr, "Hold_Types" , "u" );
-							break;
-						default :
-							continue; /*no NO-ARG option */
+								"Invalid native specification: %s",
+								native_specification);
+					if(arg[1] == '-') {
+						parse_additional_attr(pbs_attr, arg+2);
 					}
-
-					opt = 0;
-				  }
-				else
-				  {
+					else {
+						opt = arg[1];
+					}
+					
+				} else {
 					switch (opt) {
 						
@@ -715,4 +640,7 @@
 							pbs_attr->set_attr( pbs_attr, "Execution_Time" , arg );
 							break;
+						case 'h' :
+							pbs_attr->set_attr( pbs_attr, "Hold_Types" , arg );
+							break;
 						case 'A' :
 							pbs_attr->set_attr( pbs_attr, "Account_Name" , arg );
@@ -728,9 +656,5 @@
 							break;
 						case 'q' :
-							if (self->destination_queue)
-								fsd_free(self->destination_queue);
-
 							self->destination_queue = fsd_strdup( arg );
-							fsd_log_debug(("self->destination_queue = %s", self->destination_queue));
 							break;
 						case 'r' :
@@ -744,4 +668,5 @@
 							break;
 						case 'v' :
+						case 'V' :
 							pbs_attr->set_attr( pbs_attr, "Variable_List" , arg );
 							break;
@@ -750,5 +675,5 @@
 							break;
 						case 'l' :
-							parse_resources( self, pbs_attr, arg);
+							parse_resources(pbs_attr, arg);
 							break;							
 						default :
@@ -758,4 +683,5 @@
 									native_specification, opt);
 					}
+
 					opt = 0;
 				}
@@ -766,4 +692,5 @@
 						"Invalid native specification: %s",
 						native_specification);
+
 		 }
 		FINALLY
@@ -772,5 +699,6 @@
 			pbs_attr->set_attr( pbs_attr, "submit_args", native_specification);
 #endif
-			fsd_free((char *)native_spec_copy);
+			args_list->destroy(args_list);
+			fsd_free(native_spec_copy);
 		 }
 		END_TRY
@@ -778,99 +706,2 @@
 }
 
-struct attrl *
-pbsdrmaa_submit_filter(struct attrl *pbs_attr)
-{
-	fsd_log_enter(( "({pbs_attr=%p})", (void*)pbs_attr));
-
-	if (getenv(PBSDRMAA_SUBMIT_FILTER_ENV) == NULL) 
-	  {
-		return pbs_attr;
-	  } 
-	else 
-	  {
-		struct attrl *ii = NULL;
-		char *empty_args[] = { NULL };
-		int exit_status = -1;
-		const char *submit_filter = getenv(PBSDRMAA_SUBMIT_FILTER_ENV);
-		char *stdin_buf = NULL;
-		int stdin_size = 0;
-		char *stdout_buf = NULL;
-		char *stderr_buf = NULL;
-		char *output_line = NULL;
-		char *ctx = NULL;
-
-		fsd_log_debug(("Executing filter script: %s", submit_filter));
-		
-		
-		for (ii = pbs_attr; ii; ii = ii->next) 
-		  {
-			stdin_size += strlen(ii->name) + strlen(ii->value) + 2 /* '=' and '\n' */;
-			if (ii->resource)
-			  {
-				stdin_size += strlen(ii->resource) +  1; /* '.' */
-			  }
-		  }
-
-		stdin_size+=1; /* '\0' */
-
-		stdin_buf = fsd_calloc(stdin_buf, stdin_size, char);
-		stdin_buf[0] = '\0';
-
-		for (ii = pbs_attr; ii; ii = ii->next) 
-		  {
-			strcat(stdin_buf, ii->name);
-			if (ii->resource)
-			  {
-				strcat(stdin_buf, ".");
-				strcat(stdin_buf, ii->resource);
-			  }
-			strcat(stdin_buf, "=");
-			strcat(stdin_buf, ii->value);
-			strcat(stdin_buf, "\n");
-		  }
-		
-		exit_status = fsd_exec_sync(submit_filter, empty_args, stdin_buf, &stdout_buf, &stderr_buf);
-    fsd_free(stdin_buf);
-
-		if (exit_status != 0)
-		  {
-			fsd_log_error(("Filter script %s exited with non-zero code: %d", submit_filter, exit_status));
-			fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE, "Submit filter script failed (code: %d, message: %s)", exit_status, stderr_buf);
-		  }
-		
-		fsd_log_debug(("Submit filter exit_status=%d, stderr=%s", exit_status, stderr_buf));
-
-		pbsdrmaa_free_attrl(pbs_attr);
-		pbs_attr = NULL;
-
-		/* exit_status == 0 */
-		for (output_line = strtok_r(stdout_buf, "\n", &ctx);  output_line ; output_line = strtok_r(NULL, "\n", &ctx))
-		  {
-			char *attr_name = NULL;
-			char *attr_value = NULL;
-
-			attr_value = strstr(output_line,"=");
-			attr_name = output_line;
-
-			if (!attr_value)
-			  {
-				fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_FORMAT, "Invalid output line of submit filter: %s", output_line);
-			  }
-			else
-			  {
-				*attr_value = '\0';
-				attr_value++; 
-			  }
-			
-
-			pbs_attr = pbsdrmaa_add_attr( pbs_attr, attr_name, attr_value );
-      }
-
-	  fsd_free(stdout_buf);
-    fsd_free(stderr_buf);	
-
-		return pbs_attr;
-	  }
-
-}
-
