source: trunk/pbs_drmaa/submit.c @ 72

Revision 72, 21.7 KB checked in by mmamonski, 12 years ago (diff)

DRMAA submit filter - almost done

  • Property svn:keywords set to Id
Line 
1/* $Id$ */
2/*
3 *  FedStage DRMAA for PBS Pro
4 *  Copyright (C) 2006-2009  FedStage Systems
5 *
6 *  This program is free software: you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation, either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21#       include <config.h>
22#endif
23
24#include <unistd.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <pbs_ifl.h>
29#include <pbs_error.h>
30
31#include <drmaa_utils/conf.h>
32#include <drmaa_utils/drmaa.h>
33#include <drmaa_utils/drmaa_util.h>
34#include <drmaa_utils/datetime.h>
35#include <drmaa_utils/iter.h>
36#include <drmaa_utils/template.h>
37#include <pbs_drmaa/pbs_attrib.h>
38#include <pbs_drmaa/session.h>
39#include <pbs_drmaa/submit.h>
40#include <pbs_drmaa/util.h>
41
42
43
44#ifndef lint
45static char rcsid[]
46#       ifdef __GNUC__
47                __attribute__ ((unused))
48#       endif
49        = "$Id$";
50#endif
51
52static void pbsdrmaa_submit_destroy( pbsdrmaa_submit_t *self );
53
54static char *pbsdrmaa_submit_submit( pbsdrmaa_submit_t *self );
55
56static void pbsdrmaa_submit_eval( pbsdrmaa_submit_t *self );
57
58static void pbsdrmaa_submit_set( pbsdrmaa_submit_t *self, const char *pbs_attr, char *value, unsigned placeholders );
59
60static struct attrl *pbsdrmaa_submit_filter(struct attrl *pbs_attr);
61
62
63static void pbsdrmaa_submit_apply_defaults( pbsdrmaa_submit_t *self );
64static void pbsdrmaa_submit_apply_job_script( pbsdrmaa_submit_t *self );
65static void pbsdrmaa_submit_apply_job_state( pbsdrmaa_submit_t *self );
66static void pbsdrmaa_submit_apply_job_files( pbsdrmaa_submit_t *self );
67static void pbsdrmaa_submit_apply_file_staging( pbsdrmaa_submit_t *self );
68static void pbsdrmaa_submit_apply_job_resources( pbsdrmaa_submit_t *self );
69static void pbsdrmaa_submit_apply_job_environment( pbsdrmaa_submit_t *self );
70static void pbsdrmaa_submit_apply_email_notification( pbsdrmaa_submit_t *self );
71static void pbsdrmaa_submit_apply_job_category( pbsdrmaa_submit_t *self );
72
73
74pbsdrmaa_submit_t *
75pbsdrmaa_submit_new( fsd_drmaa_session_t *session,
76                const fsd_template_t *job_template, int bulk_idx )
77{
78        pbsdrmaa_submit_t *volatile self = NULL;
79        TRY
80         {
81                fsd_malloc( self, pbsdrmaa_submit_t );
82                self->session = session;
83                self->job_template = job_template;
84                self->script_filename = NULL;
85                self->destination_queue = NULL;
86                self->pbs_job_attributes = NULL;
87                self->expand_ph = NULL;
88                self->destroy = pbsdrmaa_submit_destroy;
89                self->submit = pbsdrmaa_submit_submit;
90                self->eval = pbsdrmaa_submit_eval;
91                self->set = pbsdrmaa_submit_set;
92                self->apply_defaults = pbsdrmaa_submit_apply_defaults;
93                self->apply_job_category = pbsdrmaa_submit_apply_job_category;
94                self->apply_job_script = pbsdrmaa_submit_apply_job_script;
95                self->apply_job_state = pbsdrmaa_submit_apply_job_state;
96                self->apply_job_files = pbsdrmaa_submit_apply_job_files;
97                self->apply_file_staging = pbsdrmaa_submit_apply_file_staging;
98                self->apply_job_resources = pbsdrmaa_submit_apply_job_resources;
99                self->apply_job_environment = pbsdrmaa_submit_apply_job_environment;
100                self->apply_email_notification = pbsdrmaa_submit_apply_email_notification;
101                self->apply_native_specification = pbsdrmaa_submit_apply_native_specification;
102
103                self->pbs_job_attributes = pbsdrmaa_pbs_template_new();
104                self->expand_ph = fsd_expand_drmaa_ph_new( NULL, NULL,
105                                (bulk_idx >= 0) ? fsd_asprintf("%d", bulk_idx) : NULL );
106         }
107        EXCEPT_DEFAULT
108         {
109                if( self )
110                        self->destroy( self );
111         }
112        END_TRY
113        return self;
114}
115
116
117void
118pbsdrmaa_submit_destroy( pbsdrmaa_submit_t *self )
119{
120        if( self->script_filename )
121         {
122                unlink( self->script_filename );
123                fsd_free( self->script_filename );
124         }
125        if( self->pbs_job_attributes )
126                self->pbs_job_attributes->destroy( self->pbs_job_attributes );
127        if( self->expand_ph )
128                self->expand_ph->destroy( self->expand_ph );
129        fsd_free( self->destination_queue );
130        fsd_free( self );
131}
132
133
134char *
135pbsdrmaa_submit_submit( pbsdrmaa_submit_t *self )
136{
137        volatile bool conn_lock = false;
138        struct attrl *volatile pbs_attr = NULL;
139        char *volatile job_id = NULL;
140        TRY
141         {
142                fsd_template_t *pbs_tmpl = self->pbs_job_attributes;
143                int i;
144                int tries_left = ((pbsdrmaa_session_t *)self->session)->max_retries_count;
145                int sleep_time = 1;
146
147                for( i = PBSDRMAA_N_PBS_ATTRIBUTES - 1; i >= 0; i-- ) /* down loop -> start with custom resources */
148                 {
149                        const char *name = pbs_tmpl->by_code( pbs_tmpl, i )->name;
150                        const char *value = pbs_tmpl->get_attr( pbs_tmpl, name );
151
152                        if (!value)
153                                continue;
154
155                        if ( i == PBSDRMAA_ATTR_CUSTOM_RESOURCES)
156                         {
157                                char *value_copy = fsd_strdup(value);
158                                char *tok_comma_ctx = NULL;
159                                char *res_token = NULL;
160                                /* matlab:2,simulink:1 */
161
162                                for (res_token = strtok_r(value_copy, ";", &tok_comma_ctx); res_token; res_token = strtok_r(NULL, ";", &tok_comma_ctx))
163                                 {
164                                        char *value_p = strstr(res_token, ":");
165
166                                        if (value_p)
167                                         {
168                                                char *name_p = NULL;
169                                                *value_p = '\0';
170                                                value_p++;
171                                                name_p = fsd_asprintf("Resource_List.%s",res_token);
172                                                pbs_attr = pbsdrmaa_add_attr( pbs_attr, name_p, value_p );
173                                                fsd_free(name_p);
174                                         }
175                                        else
176                                         {
177                                                fsd_exc_raise_code( FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE );
178                                         }
179                                 }
180
181                                fsd_free(value_copy);
182                         }
183                        else if (i == PBSDRMAA_ATTR_NODE_PROPERTIES)
184                         {
185                                const char *nodes_value = pbs_tmpl->get_attr( pbs_tmpl, PBSDRMAA_NODES );
186                                char *final_value = NULL;
187
188                                if (nodes_value)
189                                 {
190                                        final_value = fsd_asprintf("%s:%s",nodes_value, value);
191                                 }
192                                else
193                                 {
194                                        final_value = fsd_asprintf("1:%s", value);
195                                 }
196
197                                pbs_tmpl->set_attr( pbs_tmpl, PBSDRMAA_NODES, final_value);
198                                fsd_free(final_value);
199                         }
200                        else
201                         {
202                                pbs_attr = pbsdrmaa_add_attr( pbs_attr, name, value );
203                         }
204                 }
205
206
207                pbs_attr = pbsdrmaa_submit_filter(pbs_attr);
208
209                conn_lock = fsd_mutex_lock( &self->session->drm_connection_mutex );
210retry:
211                job_id = pbs_submit( ((pbsdrmaa_session_t*)self->session)->pbs_conn,
212                                (struct attropl*)pbs_attr, self->script_filename,
213                                self->destination_queue, NULL );
214
215                fsd_log_info(("pbs_submit(%s, %s) =%s", self->script_filename, self->destination_queue, job_id));
216
217                if( job_id == NULL )
218                {
219                        fsd_log_error(( "pbs_submit failed, pbs_errno = %d", pbs_errno ));
220                        if (pbs_errno == PBSE_PROTOCOL || pbs_errno == PBSE_EXPIRED || pbs_errno == PBSOLDE_PROTOCOL || pbs_errno == PBSOLDE_EXPIRED)
221                         {
222                                pbsdrmaa_session_t *pbsself = (pbsdrmaa_session_t*)self->session;
223
224                                fsd_log_error(( "Protocol error. Retrying..." ));
225
226                                if (pbsself->pbs_conn >= 0 )
227                                        pbs_disconnect( pbsself->pbs_conn );
228retry_connect:
229                                sleep(sleep_time++);
230                                pbsself->pbs_conn = pbs_connect( pbsself->super.contact );
231                                if( pbsself->pbs_conn < 0)
232                                 {
233                                        if (tries_left--)
234                                                goto retry_connect;
235                                        else
236                                                pbsdrmaa_exc_raise_pbs( "pbs_connect" );
237                                 }
238                                else
239                                 {
240                                        if (tries_left--)
241                                                goto retry;
242                                        else
243                                                pbsdrmaa_exc_raise_pbs( "pbs_submit" );
244                                 }
245                         }
246                        else
247                         {
248                                pbsdrmaa_exc_raise_pbs( "pbs_submit" );
249                         }
250                }
251                conn_lock = fsd_mutex_unlock( &self->session->drm_connection_mutex );
252         }
253        EXCEPT_DEFAULT
254         {
255                fsd_free( job_id );
256                fsd_exc_reraise();
257         }
258        FINALLY
259         {
260                if( conn_lock )
261                        conn_lock = fsd_mutex_unlock( &self->session->drm_connection_mutex );
262                if( pbs_attr )
263                        pbsdrmaa_free_attrl( pbs_attr );
264         }
265        END_TRY
266        return job_id;
267}
268
269
270void
271pbsdrmaa_submit_eval( pbsdrmaa_submit_t *self )
272{
273        self->apply_defaults( self );
274        self->apply_job_category( self );
275        self->apply_job_script( self );
276        self->apply_job_state( self );
277        self->apply_job_files( self );
278        self->apply_file_staging( self );
279        self->apply_job_resources( self );
280        self->apply_job_environment( self );
281        self->apply_email_notification( self );
282        self->apply_native_specification( self, NULL );
283}
284
285
286void
287pbsdrmaa_submit_set( pbsdrmaa_submit_t *self, const char *name,
288                 char *value, unsigned placeholders )
289{
290        fsd_template_t *pbs_attr = self->pbs_job_attributes;
291        TRY
292         {
293                if( placeholders )
294                        value = self->expand_ph->expand(
295                                        self->expand_ph, value, placeholders );
296                pbs_attr->set_attr( pbs_attr, name, value );
297         }
298        FINALLY
299         {
300                fsd_free( value );
301         }
302        END_TRY
303}
304
305
306void
307pbsdrmaa_submit_apply_defaults( pbsdrmaa_submit_t *self )
308{
309        fsd_template_t *pbs_attr = self->pbs_job_attributes;
310        pbs_attr->set_attr( pbs_attr, PBSDRMAA_CHECKPOINT, "u" );
311        pbs_attr->set_attr( pbs_attr, PBSDRMAA_KEEP_FILES, "n" );
312        pbs_attr->set_attr( pbs_attr, PBSDRMAA_PRIORITY, "0" );
313}
314
315
316void
317pbsdrmaa_submit_apply_job_script( pbsdrmaa_submit_t *self )
318{
319        const fsd_template_t *jt = self->job_template;
320        /* fsd_template_t *pbs_attr = self->pbs_job_attributes; */
321        fsd_expand_drmaa_ph_t *expand = self->expand_ph;
322        char *script = NULL;
323        size_t script_len;
324        const char *executable;
325        const char *wd;
326        const char *const *argv;
327        const char *input_path;
328        const char *const *i;
329
330        executable   = jt->get_attr( jt, DRMAA_REMOTE_COMMAND );
331        wd           = jt->get_attr( jt, DRMAA_WD );
332        argv         = jt->get_v_attr( jt, DRMAA_V_ARGV );
333        input_path   = jt->get_attr( jt, DRMAA_INPUT_PATH );
334
335        if( wd )
336         {
337                char *cwd = NULL;
338                cwd = expand->expand( expand, fsd_strdup(wd),
339                                FSD_DRMAA_PH_HD | FSD_DRMAA_PH_INCR );
340                expand->set( expand, FSD_DRMAA_PH_WD, cwd );
341         }
342
343        if( executable == NULL )
344                fsd_exc_raise_code( FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE );
345
346        if( input_path != NULL )
347         {
348                if( input_path[0] == ':' )
349                        input_path++;
350         }
351
352         { /* compute script length */
353                script_len = 0;
354                if( wd != NULL )
355                        script_len += strlen("cd ") + strlen(wd) + strlen("; ");
356                script_len += strlen("touch ") + strlen(((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix) + strlen("/$PBS_JOBID.started;");
357                script_len += strlen(executable);
358                if( argv != NULL )
359                        for( i = argv;  *i != NULL;  i++ )
360                                script_len += 3+strlen(*i);
361                if( input_path != NULL )
362                        script_len += strlen(" <") + strlen(input_path);
363
364                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");
365         }
366
367        fsd_calloc( script, script_len+1, char );
368
369         {
370                char *s;
371                s = script;
372                if( wd != NULL )
373                        s += sprintf( s, "cd %s; ", wd );
374                s += sprintf( s, "touch %s/$PBS_JOBID.started;", ((pbsdrmaa_session_t *)self->session)->job_exit_status_file_prefix);
375                s += sprintf( s, "%s", executable );
376                if( argv != NULL )
377                        for( i = argv;  *i != NULL;  i++ )
378                                s += sprintf( s, " '%s'", *i );
379                if( input_path != NULL )
380                        s += sprintf( s, " <%s", input_path );
381
382                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);
383
384                fsd_assert( s == script+script_len );
385         }
386
387        script = expand->expand( expand, script,
388                        FSD_DRMAA_PH_HD | FSD_DRMAA_PH_WD | FSD_DRMAA_PH_INCR );
389
390        /* pbs_attr->set_attr( pbs_attr, "!script", script ); */
391
392        self->script_filename = pbsdrmaa_write_tmpfile( script, strlen(script) );
393        fsd_free( script );
394}
395
396
397void
398pbsdrmaa_submit_apply_job_state( pbsdrmaa_submit_t *self )
399{
400        const fsd_template_t *jt = self->job_template;
401        fsd_template_t *pbs_attr = self->pbs_job_attributes;
402        const char *job_name = NULL;
403        const char *submit_state = NULL;
404        const char *drmaa_start_time = NULL;
405
406        job_name = jt->get_attr( jt, DRMAA_JOB_NAME );
407        submit_state = jt->get_attr( jt, DRMAA_JS_STATE );
408        drmaa_start_time = jt->get_attr( jt, DRMAA_START_TIME );
409
410        if( job_name != NULL )
411                pbs_attr->set_attr( pbs_attr, PBSDRMAA_JOB_NAME, job_name );
412
413        if( submit_state != NULL )
414         {
415                const char *hold_types;
416                if( !strcmp(submit_state, DRMAA_SUBMISSION_STATE_ACTIVE) )
417                        hold_types = "n";
418                else if( !strcmp(submit_state, DRMAA_SUBMISSION_STATE_HOLD) )
419                        hold_types = "u";
420                else
421                        fsd_exc_raise_fmt( FSD_ERRNO_INVALID_VALUE,
422                                        "invalid value of %s attribute (%s|%s)",
423                                        DRMAA_JS_STATE, DRMAA_SUBMISSION_STATE_ACTIVE,
424                                        DRMAA_SUBMISSION_STATE_HOLD );
425                pbs_attr->set_attr( pbs_attr, PBSDRMAA_HOLD_TYPES, hold_types );
426         }
427
428        if( drmaa_start_time != NULL )
429         {
430                time_t start_time;
431                char pbs_start_time[20];
432                struct tm start_time_tm;
433                start_time = fsd_datetime_parse( drmaa_start_time );
434                localtime_r( &start_time, &start_time_tm );
435                sprintf( pbs_start_time, "%04d%02d%02d%02d%02d.%02d",
436                                start_time_tm.tm_year + 1900,
437                                start_time_tm.tm_mon + 1,
438                                start_time_tm.tm_mday,
439                                start_time_tm.tm_hour,
440                                start_time_tm.tm_min,
441                                start_time_tm.tm_sec
442                                );
443                pbs_attr->set_attr( pbs_attr, PBSDRMAA_EXECUTION_TIME, pbs_start_time );
444         }
445}
446
447
448void
449pbsdrmaa_submit_apply_job_files( pbsdrmaa_submit_t *self )
450{
451        const fsd_template_t *jt = self->job_template;
452        fsd_template_t *pbs_attr = self->pbs_job_attributes;
453        const char *join_files;
454        bool b_join_files;
455        int i;
456
457        for( i = 0;  i < 2;  i++ )
458         {
459                const char *drmaa_name;
460                const char *pbs_name;
461                const char *path;
462
463                if( i == 0 )
464                 {
465                        drmaa_name = DRMAA_OUTPUT_PATH;
466                        pbs_name = PBSDRMAA_OUTPUT_PATH;
467                 }
468                else
469                 {
470                        drmaa_name = DRMAA_ERROR_PATH;
471                        pbs_name = PBSDRMAA_ERROR_PATH;
472                 }
473
474                path = jt->get_attr( jt, drmaa_name );
475                if( path != NULL )
476                 {
477                        if( path[0] == ':' )
478                                path++;
479                        self->set(self, pbs_name, fsd_strdup(path), FSD_DRMAA_PH_HD | FSD_DRMAA_PH_WD | FSD_DRMAA_PH_INCR);
480                 }
481         }
482
483        join_files = jt->get_attr( jt, DRMAA_JOIN_FILES );
484        b_join_files = join_files != NULL  &&  !strcmp(join_files,"1");
485        pbs_attr->set_attr( pbs_attr, PBSDRMAA_JOIN_FILES, (b_join_files ? "y" : "n") );
486}
487
488
489void
490pbsdrmaa_submit_apply_file_staging( pbsdrmaa_submit_t *self )
491{
492        /* TODO */
493}
494
495
496void
497pbsdrmaa_submit_apply_job_resources( pbsdrmaa_submit_t *self )
498{
499        const fsd_template_t *jt = self->job_template;
500        fsd_template_t *pbs_attr = self->pbs_job_attributes;
501        const char *cpu_time_limit = NULL;
502        const char *walltime_limit = NULL;
503
504        cpu_time_limit = jt->get_attr( jt, DRMAA_DURATION_HLIMIT );
505        walltime_limit = jt->get_attr( jt, DRMAA_WCT_HLIMIT );
506        if( cpu_time_limit )
507         {
508                pbs_attr->set_attr( pbs_attr, "Resource_List.pcput", cpu_time_limit );
509                pbs_attr->set_attr( pbs_attr, "Resource_List.cput", cpu_time_limit );
510         }
511        if( walltime_limit )
512                pbs_attr->set_attr( pbs_attr, "Resource_List.walltime", walltime_limit );
513}
514
515
516
517void
518pbsdrmaa_submit_apply_job_environment( pbsdrmaa_submit_t *self )
519{
520        const fsd_template_t *jt = self->job_template;
521        const char *const *env_v;
522        const char *jt_wd;
523        char *wd;
524        char *env_c = NULL;
525        int ii = 0, len = 0;
526
527        env_v = jt->get_v_attr( jt, DRMAA_V_ENV);
528        jt_wd    = jt->get_attr( jt, DRMAA_WD );
529       
530        if (!jt_wd)
531        {
532                wd = fsd_getcwd();
533        }
534        else
535        {
536                wd = fsd_strdup(jt_wd);
537        }
538
539        if (env_v)
540         {
541                ii = 0;
542                while (env_v[ii])
543                 {
544                        len += strlen(env_v[ii]) + 1;
545                        ii++;
546                 }
547         }
548       
549        len+= strlen("PBS_O_WORKDIR=") + strlen(wd);
550
551        fsd_calloc(env_c, len + 1, char);
552        env_c[0] = '\0';
553
554        if (env_v)
555        {
556                ii = 0;
557                while (env_v[ii]) {
558                        strcat(env_c, env_v[ii]);
559                        strcat(env_c, ",");
560                        ii++;
561                }
562
563        }
564       
565        strcat(env_c, "PBS_O_WORKDIR=");
566        strcat(env_c, wd);
567
568        self->pbs_job_attributes->set_attr(self->pbs_job_attributes, "Variable_List", env_c);
569
570        fsd_free(env_c);
571        fsd_free(wd);
572}
573
574
575void
576pbsdrmaa_submit_apply_email_notification( pbsdrmaa_submit_t *self )
577{
578        /* TODO */
579}
580
581
582void
583pbsdrmaa_submit_apply_job_category( pbsdrmaa_submit_t *self )
584{
585        const char *job_category = NULL;
586        const char *category_spec = NULL;
587        fsd_conf_option_t *value = NULL;
588
589        job_category = self->job_template->get_attr(
590                        self->job_template, DRMAA_JOB_CATEGORY );
591        if( job_category == NULL  ||  job_category[0] == '\0' )
592                job_category = "default";
593        value = fsd_conf_dict_get( self->session->job_categories,
594                        job_category );
595        if( value != NULL  &&  value->type == FSD_CONF_STRING )
596                category_spec = value->val.string;
597        if( category_spec != NULL )
598                self->apply_native_specification( self, category_spec );
599}
600
601static const char *get_job_env(pbsdrmaa_submit_t *self, const char *env_name)
602{
603        const fsd_template_t *jt = self->job_template;
604        const char *const *env_v = jt->get_v_attr( jt, DRMAA_V_ENV);
605        int ii = 0;
606
607        while (env_v[ii])
608         {
609                char *eq_p = strstr(env_v[ii], "=");
610
611                if ((eq_p) && (strncmp(env_v[ii], env_name, eq_p - env_v[ii]) == 0))
612                                return ++eq_p;
613
614                ii++;
615         }
616
617        return NULL;
618}
619
620static void parse_resources(pbsdrmaa_submit_t *self, fsd_template_t *pbs_attr,const char *resources)
621{
622        char * volatile name = NULL;
623        char *arg = NULL;
624        char *value = NULL;
625        char *ctxt = NULL;
626        char * volatile resources_copy = fsd_strdup(resources);
627
628        TRY
629          {
630                for (arg = strtok_r(resources_copy, ",", &ctxt); arg; arg = strtok_r(NULL, ",",&ctxt) )
631                {
632                        char *psep = strchr(arg, '=');
633
634                        if (psep)
635                        {
636                                *psep = '\0';
637                                name = fsd_asprintf("Resource_List.%s", arg);
638                                value = ++psep;
639                                if (value[0] == '$' && get_job_env(self, value + 1))
640                                        pbs_attr->set_attr( pbs_attr, name , get_job_env(self, value + 1) ); /*get value from job env variable */
641                                else
642                                        pbs_attr->set_attr( pbs_attr, name , value );
643                                fsd_free(name);
644                                name = NULL;
645                        }
646                        else
647                        {
648                                fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE, "Invalid native specification: %s (Invalid resource specification: %s)", resources, arg);
649                        }
650                }
651          }
652        FINALLY
653          {
654                fsd_free(name);
655                fsd_free(resources_copy);
656          }
657        END_TRY
658}
659
660static void parse_additional_attr(fsd_template_t *pbs_attr,const char *add_attr)
661{
662        char * volatile name = NULL;
663        char *arg = NULL;
664        char *value = NULL;
665        char *ctxt = NULL, *ctxt2 = NULL;
666        char * volatile add_attr_copy = fsd_strdup(add_attr);
667
668        TRY
669          {
670                for (arg = strtok_r(add_attr_copy, ";", &ctxt); arg; arg = strtok_r(NULL, ";",&ctxt) )
671                {
672                        name = fsd_strdup(strtok_r(arg, "=", &ctxt2));
673                        value = strtok_r(NULL, "=", &ctxt2);
674                        pbs_attr->set_attr( pbs_attr, name , value );
675                        fsd_free(name);
676                        name = NULL;
677                }
678          }
679        FINALLY
680          {
681                fsd_free(name);
682                fsd_free(add_attr_copy);
683          }
684        END_TRY
685}
686
687
688void
689pbsdrmaa_submit_apply_native_specification( pbsdrmaa_submit_t *self,
690                const char *native_specification )
691{
692        fsd_log_enter(( "({native_specification=%s})", native_specification ));
693
694        if( native_specification == NULL )
695                native_specification = self->job_template->get_attr(
696                                self->job_template, DRMAA_NATIVE_SPECIFICATION );
697        if( native_specification == NULL )
698                return;
699
700        {
701                fsd_template_t *pbs_attr = self->pbs_job_attributes;
702                char *arg = NULL;
703                volatile char * native_spec_copy = fsd_strdup(native_specification);
704                char * ctxt = NULL;
705                int opt = 0;
706
707                TRY
708                  {
709                        for (arg = strtok_r((char *)native_spec_copy, " \t", &ctxt); arg; arg = strtok_r(NULL, " \t",&ctxt) ) {
710                                if (!opt)
711                                  {
712                                        if ( (arg[0] != '-') || (strlen(arg) != 2) )
713                                                fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE,
714                                                        "Invalid native specification: -o(ption) expected (arg=%s native=%s).",
715                                                        arg, native_specification);
716
717                                        opt = arg[1];
718
719                                        /* handle NO-arg options */
720
721                                        switch (opt) {
722                                                case 'h' :
723                                                        pbs_attr->set_attr( pbs_attr, "Hold_Types" , "u" );
724                                                        break;
725                                                default :
726                                                        continue; /*no NO-ARG option */
727                                        }
728
729                                        opt = 0;
730                                  }
731                                else
732                                  {
733                                        switch (opt) {
734                                               
735                                                case 'W' :
736                                                        parse_additional_attr(pbs_attr, arg);
737                                                        break;
738                                                case 'N' :
739                                                        pbs_attr->set_attr( pbs_attr, "Job_Name" , arg );
740                                                        break;
741                                                case 'o' :
742                                                        pbs_attr->set_attr( pbs_attr, "Output_Path" , arg );
743                                                        break;
744                                                case 'e' :
745                                                        pbs_attr->set_attr( pbs_attr, "Error_Path" , arg );
746                                                        break;
747                                                case 'j' :
748                                                        pbs_attr->set_attr( pbs_attr, "Join_Path" , arg );
749                                                        break;
750                                                case 'm' :
751                                                        pbs_attr->set_attr( pbs_attr, "Mail_Points" , arg );
752                                                        break;
753                                                case 'a' :
754                                                        pbs_attr->set_attr( pbs_attr, "Execution_Time" , arg );
755                                                        break;
756                                                case 'A' :
757                                                        pbs_attr->set_attr( pbs_attr, "Account_Name" , arg );
758                                                        break;
759                                                case 'c' :
760                                                        pbs_attr->set_attr( pbs_attr, "Checkpoint" , arg );
761                                                        break;
762                                                case 'k' :
763                                                        pbs_attr->set_attr( pbs_attr, "Keep_Files" , arg );
764                                                        break;
765                                                case 'p' :
766                                                        pbs_attr->set_attr( pbs_attr, "Priority" , arg );
767                                                        break;
768                                                case 'q' :
769                                                        if (self->destination_queue)
770                                                                fsd_free(self->destination_queue);
771
772                                                        self->destination_queue = fsd_strdup( arg );
773                                                        fsd_log_debug(("self->destination_queue = %s", self->destination_queue));
774                                                        break;
775                                                case 'r' :
776                                                        pbs_attr->set_attr( pbs_attr, "Rerunable" , arg );
777                                                        break;
778                                                case 'S' :
779                                                        pbs_attr->set_attr( pbs_attr, "Shell_Path_List" , arg );
780                                                        break;
781                                                case 'u' :
782                                                        pbs_attr->set_attr( pbs_attr, "User_List" , arg );
783                                                        break;
784                                                case 'v' :
785                                                        pbs_attr->set_attr( pbs_attr, "Variable_List" , arg );
786                                                        break;
787                                                case 'M' :
788                                                        pbs_attr->set_attr( pbs_attr, "Mail_Users" , arg );
789                                                        break;
790                                                case 'l' :
791                                                        parse_resources( self, pbs_attr, arg);
792                                                        break;                                                 
793                                                default :
794                                                       
795                                                        fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE,
796                                                                        "Invalid native specification: %s (Unsupported option: -%c)",
797                                                                        native_specification, opt);
798                                        }
799                                        opt = 0;
800                                }
801                        }
802
803                        if (opt) /* option without optarg */
804                                fsd_exc_raise_fmt(FSD_DRMAA_ERRNO_INVALID_ATTRIBUTE_VALUE,
805                                                "Invalid native specification: %s",
806                                                native_specification);
807                 }
808                FINALLY
809                 {
810#ifndef PBS_PROFESSIONAL
811                        pbs_attr->set_attr( pbs_attr, "submit_args", native_specification);
812#endif
813                        fsd_free((char *)native_spec_copy);
814                 }
815                END_TRY
816        }
817}
818
819struct attrl *
820pbsdrmaa_submit_filter(struct attrl *pbs_attr)
821{
822        fsd_log_enter(( "({pbs_attr=%p})", pbs_attr));
823
824        if (getenv(PBSDRMAA_SUBMIT_FILTER_ENV) == NULL) {
825                return pbs_attr;
826        } else {
827                struct attrl *ii = NULL;
828                const char *submit_filter = getenv(PBSDRMAA_SUBMIT_FILTER_ENV);
829
830                fsd_log_info(("Executing filter script: %s", submit_filter));
831
832                for (ii = pbs_attr; ii; ii = ii->next) {
833                        fsd_log_info(("FILTER: %s=%s ", ii->name, ii->value));
834                }
835
836                return pbs_attr;
837        }
838
839
840}
841
Note: See TracBrowser for help on using the repository browser.