4gl development question
Posted in 2005
Topics: Connectivity: ESQL/C, 4GL & Embedded SQL
The way our 4gl application has evolved we make use of system calls to execute other programs rather than linking in that functionality directly to the calling program. For example this leads to the following type of code program1: begin work ....... commit work run "program2" begin work ....... commit work with the transactions being commited prior to the call to avoid locking difficulties. This has worked (made to work) but has never been ideal as we should really have a single transaction. Now we have a requirement to keep the work in a single transaction I was wondering if there is an elegant way of having two 4gl programs effectively share the same connection (and transaction). My fallback is to rework the code and link in the appropriate modules but this will lead to bigger executables, more maintenance and will take some time to achieve ... I'd rather not do this. My thinking was that I could use esqlc to replace the system call in program1 and the main module of program2. This would involve binding the programs together via sockets, passing the named connection from program1 to program2, setting the connection within program2 and fgl_start program2. I'm sure this problem has been seen before so the big questions are is this approach doable and what are there alternatives ? Regards Neil
Neil wrote: > The way our 4gl application has evolved we make use of system calls to > execute other programs rather than linking in that functionality > directly to the calling program. > > For example this leads to the following type of code > > program1: begin work > ....... > commit work > run "program2" > begin work > ....... > commit work > > with the transactions being commited prior to the call to avoid locking > difficulties. I suppose so. Ouch! > This has worked (made to work) but has never been ideal as we should > really have a single transaction. Oh dear. > Now we have a requirement to keep the work in a single transaction I was > wondering if there is an elegant way of having two 4gl programs > effectively share the same connection (and transaction). My fallback is > to rework the code and link in the appropriate modules but this will > lead to bigger executables, more maintenance and will take some time to > achieve ... I'd rather not do this. Maybe so. Unless you start running XA transactions - which involves some C glue code at the least (not to mention the odd headache or ten; you should be getting plenty of adverts for pills, not all for headaches, in your spam filter) - you are pretty much going to have to combine applications. > My thinking was that I could use esqlc to replace the system call in > program1 and the main module of program2. This would involve binding the > programs together via sockets, passing the named connection from > program1 to program2, setting the connection within program2 and > fgl_start program2. You might, conceivably, get something along these lines to work; no guarantees, and no support - especially not support. OTOH, it more likely won't work. 'The named connection' isn't going to fly; that's a property of the client library in one executable. What you might be able to pass is the open file descriptor corresponding to the socket. Goofy, system depdendent stuff, with no documented way to find the file descrptor for the connection to IDS, but IDS passes file descriptors between VPs internally, so you can probably do it too. > I'm sure this problem has been seen before so the big questions are is > this approach doable and what are there alternatives ? Probably not. Write the code as a single program. -- Jonathan Leffler #include <disclaimer.h> Email: jleffler@earthlink.net, jleffler@us.ibm.com Guardian of DBD::Informix v2003.04 -- http://dbi.perl.org/
Neil wrote: > The way our 4gl application has evolved we make use of system calls to > execute other programs rather than linking in that functionality > directly to the calling program. > > For example this leads to the following type of code > > program1: begin work > ....... > commit work > run "program2" > begin work > ....... > commit work > > with the transactions being commited prior to the call to avoid > locking difficulties. > > This has worked (made to work) but has never been ideal as we should > really have a single transaction. > > Now we have a requirement to keep the work in a single transaction I > was wondering if there is an elegant way of having two 4gl programs > effectively share the same connection (and transaction). My fallback > is to rework the code and link in the appropriate modules but this > will lead to bigger executables, more maintenance and will take some > time to achieve ... I'd rather not do this. > > My thinking was that I could use esqlc to replace the system call in > program1 and the main module of program2. This would involve binding > the programs together via sockets, passing the named connection from > program1 to program2, setting the connection within program2 and > fgl_start program2. > > I'm sure this problem has been seen before so the big questions are is > this approach doable and what are there alternatives ? > > Regards > Neil I may be stating the obvious, but if you set isolation mode to committed read, set lock mode to wait, declare your cursors with hold, and commit work - begin work every N transactions in all the programs that access the table(s) you have, you ought to be able to do what you appear to be talking about -- and it won't matter if it's 4-GL or ESQL/C or whatever. If you're doing what I think you're doing -- executing programs from within a program -- you may want to consider doing it like this in an ESQL/C program. Here's a code fragment that builds up a command to execute from within an ESQL/C program, does fork and execvp, and waits for that to complete (this is pretty much the mechanism the shell uses when you type a command and hit the carriage return): char *args [6]; /* arguments for execvp */ pid_t fpid = (pid_t) 0; . . . /* stack up arguments for sort */ (void) sprintf (sql_line, "%s/BAD_payer.unl", dir_nam); args [0] = "/bin/sort"; /* the command */ args [1] = "-u"; /* unique */ args [2] = "-o"; /* output same as input */ args [3] = sql_line; /* output file name */ args [4] = sql_line; /* input file name */ args [5] = (char *) NULL; /* and a terminator */ /* * create a new process, fork and exec the command * arguments contained in the args[] array of pointers * (mess with this mechanism at your peril) */ if ((fpid = fork ()) < (pid_t) 0) (void) fprintf (stderr, "%s:\\tcan't fork\\n", argv [0]); else if (fpid > (pid_t) 0) (void) wait ((int *) NULL); else if (fpid == (pid_t) 0) { if (execvp (args [0], args)) { (void) fprintf (stderr, "%s:\\tcan't execute %s\\n", argv [0], args [0]); perror ("execvp"); } } The important thing is "wait;" i.e., fork, execute whatever you're doing and wait for it to complete before going on (if I remember correctly, 4-GL "system" calls don't do that). That in combination with the isolation mode, lock mode, and commit work - begin work may just do what you want. Hope this helps rather than hurts.
I may be way off - but can you use shared libraries rather than
executables ?
Once you've linked the application - that still gives you the chance to
change just those libraries without a complete recompile etc.
Using c4gl...
mylib.4gl :
function inc(a)
define a integer
return a+1
end function
myprog.4gl :
main
define a integer
let a=inc(1)
display a
end main
$ c4gl --shared mylib.4gl -o libmylib.so
$ c4gl -o myprog myprog.4gl -L. -lmylib
Not that it will help - but Aubit4GL allows calls to shared libraries
directly without even linking them to your program (notation is similar to
perl) :
$ 4glpc -as-dll mylib.4gl -o mylib.so
myprog.4gl:
main
define a integer
let a=mylib::inc(1)
display a
end main
$ 4glpc myprog.4gl -o myprog
$ ./myprog2
Neil wrote:
> The way our 4gl application has evolved we make use of system calls to
> execute other programs rather than linking in that functionality
> directly to the calling program.
>
> For example this leads to the following type of code
>
> program1: begin work
> .......
> commit work
> run "program2"
> begin work
> .......
> commit work
>
> with the transactions being commited prior to the call to avoid locking
> difficulties.
>
> This has worked (made to work) but has never been ideal as we should
> really have a single transaction.
>
> Now we have a requirement to keep the work in a single transaction I was
> wondering if there is an elegant way of having two 4gl programs
> effectively share the same connection (and transaction). My fallback is
> to rework the code and link in the appropriate modules but this will
> lead to bigger executables, more maintenance and will take some time to
> achieve ... I'd rather not do this.
>
> My thinking was that I could use esqlc to replace the system call in
> program1 and the main module of program2. This would involve binding the
> programs together via sockets, passing the named connection from
> program1 to program2, setting the connection within program2 and
> fgl_start program2.
>
> I'm sure this problem has been seen before so the big questions are is
> this approach doable and what are there alternatives ?
>
> Regards
> Neil