source: trunk/pbs_drmaa/submit.c @ 91

Revision 91, 22.5 KB checked in by mmamonski, 11 years ago (diff)

Fixed handling of the PBSDRMAA_JOIN_FILES attribute

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