source: trunk/pbs_drmaa/submit.c @ 67

Revision 67, 21.2 KB checked in by mmamonski, 12 years ago (diff)

fixed retry semantics in pbs_submit

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