• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/maloc/src/psh/psh.c

00001 /*
00002  * ***************************************************************************
00003  * MALOC = < Minimal Abstraction Layer for Object-oriented C >
00004  * Copyright (C) 1994--2008 Michael Holst
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019  *
00020  * rcsid="$Id: psh.c,v 1.40 2008/03/12 05:13:58 fetk Exp $"
00021  * ***************************************************************************
00022  */
00023 
00024 /*
00025  * ***************************************************************************
00026  * File:     psh.c
00027  *
00028  * Purpose:  Vsh_pshell w/ infrastructure (parallel extension of Vsh_shell).
00029  *
00030  * Author:   Michael Holst
00031  * ***************************************************************************
00032  */
00033 
00034 #include "psh_p.h"
00035 
00036 VEMBED(rcsid="$Id: psh.c,v 1.40 2008/03/12 05:13:58 fetk Exp $")
00037 
00038 /* parallel shell commands */
00039 typedef enum PSH_command {
00040     pshcom_none,
00041     pshcom_ignore,
00042     pshcom_set,
00043     pshcom_help,
00044     pshcom_vmp_snd,
00045     pshcom_vmp_rcv,
00046     pshcom_vmp_bar
00047 } PSH_command;
00048 
00049 /* local variables we need (THIS CODE IS NOT REENTRANT!) */
00050 VPRIVATE Vmp *theeVMP = VNULL;
00051 VPRIVATE Vsh *theePSH = VNULL;
00052 VPRIVATE int (*theeFunc)(void *thee, int argc, char **argv) = VNULL;
00053 
00054 /*
00055  * ***************************************************************************
00056  * Routine:  Vsh_publishVars
00057  *
00058  * Purpose:  Publish environment variables.
00059  *
00060  * Author:   Michael Holst
00061  * ***************************************************************************
00062  */
00063 VPRIVATE void PSH_publishVars(Vsh *thee)
00064 {
00065     int i, numVars = 4;
00066     typedef struct vshVars {
00067         char envi[VMAX_ARGLEN];
00068         char valu[VMAX_ARGLEN];
00069         char info[VMAX_ARGLEN];
00070     } vshVars;
00071     vshVars envVars[] = {
00072         /* --------   -----       ----------- */
00073         /* VARIABLE   VALUE       EXPLANATION */
00074         /* --------   -----       ----------- */
00075         /* ===[ VMP=4 ]=== */
00076         { "VMP_I",    "0",
00077             "VMP id (my VMP process number)" },
00078         { "VMP_N",    "1",
00079             "VMP nproc (number of VMP processes in this execution)" },
00080         { "VMP_P",    "0",
00081             "VMP send/recv partner (current VMP send/recv partner)" },
00082         { "VMP_F",    "-1",
00083             "VMP cmd effect (-1=all,0=proc0,1=proc1,...,N=procN)" }
00084     };  
00085 
00086     /* publish remaining variables */
00087     for (i=0; i<numVars; i++) {
00088         VASSERT( Vsh_putenv(     thee, envVars[i].envi, envVars[i].valu )
00089               && Vsh_putenvInfo( thee, envVars[i].envi, envVars[i].info ) );
00090     }
00091 }
00092 
00093 /*
00094  * ***************************************************************************
00095  * Routine:  PSH_getCmd
00096  *
00097  * Purpose:  Decode the input string into a legal command.
00098  *
00099  * Author:   Michael Holst
00100  * ***************************************************************************
00101  */
00102 VPRIVATE PSH_command PSH_getCmd(int argc, char **argv)
00103 {
00104     PSH_command theCmd = pshcom_none;
00105     if (!strcmp(argv[0],"")) {
00106         theCmd = pshcom_none;
00107     } else if (!strcmp(argv[0],"set")) {
00108         theCmd = pshcom_set;
00109     } else if (!strcmp(argv[0],"help")) {
00110         theCmd = pshcom_help;
00111     } else if (!strcmp(argv[0],"vmp_snd")) {
00112         theCmd = pshcom_vmp_snd;
00113     } else if (!strcmp(argv[0],"vmp_rcv")) {
00114         theCmd = pshcom_vmp_rcv;
00115     } else if (!strcmp(argv[0],"vmp_bar")) {
00116         theCmd = pshcom_vmp_bar;
00117     } else {
00118         theCmd = pshcom_none;
00119     }
00120     return theCmd;
00121 }
00122 
00123 /*
00124  * ***************************************************************************
00125  * Routine:  PSH_builtin
00126  *
00127  * Purpose: Parallel extensions to the vsh.
00128  *
00129  * Return codes (required):
00130  *
00131  *     rc=0   --> Psh does not know about this command
00132  *     rc=1   --> Psh handled this command sucessfully
00133  *     rc=2   --> Psh handled this command sucessfully and wants to exit!
00134  *
00135  * Author:   Michael Holst
00136  * ***************************************************************************
00137  */
00138 VPRIVATE int PSH_builtin(void *pthee, int argc, char **argv)
00139 {
00140     int rc, me, src, des, bufLen;
00141     unsigned int bufLenMessage;
00142     char *bufPtr;
00143     PSH_command theCmd;
00144 
00145     static int init=0;
00146     static char vmp[VMAX_BUFSIZE], vmp_min[VMAX_BUFSIZE];
00147     const char *stmp;
00148 
00149     /* one-time intialization */
00150     if (!init) {
00151         init=1;
00152 
00153         /* make the minimal vmp message (%s slots = 2) */
00154         stmp = "%s: pVsh-layer Help Menu: \n"
00155             "    help vmp  --> Help on %s communication commands\n";
00156         sprintf(vmp_min,stmp,theePSH->PR,theePSH->PR);
00157 
00158         /* make the full vmp message (%s slots = 1) */
00159         stmp = "%s: Parallel shell extensions: \n"
00160             "    vmp_snd   --> VMP send local buffer to selected proc\n"
00161             "    vmp_rcv   --> VMP recv into local buffer\n"
00162             "    vmp_bar   --> VMP synchronization barrier\n";
00163         sprintf(vmp,stmp,theePSH->PR);
00164 
00165         /* publish VMP variables we need */
00166         PSH_publishVars(theePSH);
00167 
00168         /* initialize VMP variables */
00169         if (theeVMP != VNULL) {
00170             Vsh_putenvInt(theePSH,"VMP_I",Vmp_rank(theeVMP));
00171             Vsh_putenvInt(theePSH,"VMP_N",Vmp_size(theeVMP));
00172         } else {
00173             Vsh_putenvInt(theePSH,"VMP_I",0);
00174             Vsh_putenvInt(theePSH,"VMP_N",1);
00175         }
00176     }
00177 
00178     /* get the command */
00179     theCmd = PSH_getCmd(argc, argv);
00180 
00181     /*
00182      * see if we are supposed to execute the command
00183      * parallel mode: we execute the command in only three situations:
00184      *     (1) everyone has the focus (VMP_F==-1)
00185      *     (2) we alone have the focus (VMP_F==VMP_I)
00186      *     (3) we are setting the focus (set VMP_F X)
00187      */
00188     if ( Vsh_getenvInt(theePSH,"VMP_F") == -1 ) {
00189         /*
00190          * everyone is supposed to execute it
00191          */
00192         rc = 0;
00193     } else if ( Vsh_getenvInt(theePSH,"VMP_F") 
00194              == Vsh_getenvInt(theePSH,"VMP_I") ) {
00195         /*
00196          * only we are supposed to execute it
00197          */
00198         rc = 0;
00199     } else if ( (theCmd == pshcom_set)
00200              && (!strcmp(argv[1],"VMP_F"))
00201              && (argc == 3) ) {
00202         /*
00203          * OK, it is a legal "set VMP_F X" command.
00204          * SO, we ARE supposed to execute it.
00205          * NOTE: we won't recognize "set" as one of our
00206          *       legal commands, so it will fall through
00207          *       to the base VSH builtin which will deal with it.
00208          */
00209         rc = 0;
00210     } else {
00211         /*
00212          * we are supposed to ignore it
00213          */
00214         theCmd = pshcom_ignore;
00215         rc = 1;
00216     }
00217 
00218     /* have a look at the command if we are not ignoring it */
00219     if (theCmd != pshcom_ignore) {
00220 
00221         /* the normal vsh shell gets first shot at the command */
00222         if (theeFunc != VNULL) {
00223             rc = (*(theeFunc))(pthee,argc,argv);
00224             if (rc != 0) return rc;
00225         }
00226 
00227         /* decode and execute the command */
00228         switch (theCmd) {
00229 
00230           case pshcom_help:
00231             if (argc==1) {
00232                 Vnm_print(1,"%s",vmp_min);
00233                 rc = 0;  /* pretend we didn't see it so subshell can help too */
00234             } else if ((argc==2) && (!strcmp(argv[1],"vmp"))) {
00235                 Vnm_print(1,"%s",vmp);
00236                 rc = 1;
00237             } else {
00238                 rc = 0;  /* pretend we didn't see it so subshell can help too */
00239             }
00240             break;
00241 
00242           case pshcom_vmp_snd:
00243             me     = Vsh_getenvInt(theePSH,"VMP_I");
00244             des    = Vsh_getenvInt(theePSH,"VMP_P");
00245             bufLen = theePSH->bufsize;
00246             bufPtr = theePSH->buf;
00247 
00248             Vnm_print(2,"Vsh_builtIn: [%d --> %d] sending mesg size=<%d>\n",
00249                 me, des, bufLen);
00250             bufLenMessage = (unsigned int)bufLen;
00251             Vmp_send(theeVMP, des, (char*)&bufLenMessage, 4);
00252 
00253             Vnm_print(2,"Vsh_builtIn: [%d --> %d] sending the real mesg.\n",
00254                 me, des);
00255             Vmp_send(theeVMP, des, bufPtr, bufLen);
00256             rc = 1;
00257             break;
00258 
00259           case pshcom_vmp_rcv:
00260             me  = Vsh_getenvInt(theePSH,"VMP_I");
00261             src = Vsh_getenvInt(theePSH,"VMP_P");
00262 
00263             Vmp_recv(theeVMP, src, (char*)&bufLenMessage, 4);
00264             bufLen = (int)bufLenMessage;
00265             Vnm_print(2,"Vsh_builtIn: [%d <-- %d] received mesg size=<%d>\n",
00266                 me, src, bufLen);
00267 
00268             /* bufPtr = Vmem_malloc( theePSH->vmem, bufLen, sizeof(char) ); */
00269             bufPtr = calloc( bufLen, sizeof(char) );
00270 
00271             Vmp_recv(theeVMP, src, bufPtr, bufLen);
00272             Vnm_print(2,"Vsh_builtIn: [%d <-- %d] received the real mesg.\n",
00273                 me, src);
00274             theePSH->bufsize = bufLen;
00275             theePSH->buf = bufPtr;
00276             rc = 1;
00277             break;
00278 
00279           case pshcom_vmp_bar:
00280             Vmp_barr(theeVMP);
00281             rc = 1;
00282             break;
00283 
00284           case pshcom_ignore:
00285             /* truly ignore; keep subsequent layers from trying to execute! */
00286             rc = 1;
00287             break;
00288 
00289           default:
00290             rc = 0;
00291             break;
00292         }
00293     }
00294 
00295     return rc;
00296 }
00297 
00298 /*
00299  * ***************************************************************************
00300  * Routine:  Vsh_pshell
00301  *
00302  * Purpose:  Drop-in replacement for <Vsh_shell> giving parallel extensions.
00303  *
00304  * Author:   Michael Holst
00305  * ***************************************************************************
00306  */
00307 VPUBLIC int Vsh_pshell(Vsh *thee, char *pPR, void *pthee,
00308     int (*builtin)(void *thee, int argc, char **argv))
00309 {
00310     int rc;
00311 
00312     /* don't let shell process args (e.g. MPI wants to use argc/argv itself) */
00313     thee->processArgs = 0;
00314     
00315     /* save the function pointer to be called by our parallel layer */
00316     theeFunc = builtin;
00317     theePSH = thee;
00318 
00319     /* create communication object (do first so file i/o gets tagged) */
00320     theeVMP = Vmp_ctor();
00321 
00322     /* start the vsh, slipping our extra parallel layer in */
00323     rc = Vsh_shell(thee, pPR, pthee, &PSH_builtin);
00324 
00325     /* destroy communication object */
00326     Vmp_dtor( &(theeVMP) );
00327 
00328     /* return */
00329     return rc;
00330 }
00331 

Generated on Wed Oct 20 2010 11:12:15 for APBS by  doxygen 1.7.2