For Programmers: Free Programming Magazines  


Home > Archive > Cobol > April 2004 > Deploying over IIS and VB









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Deploying over IIS and VB
sb

2004-03-26, 11:00 pm

Hello,

I have Cobol Dlls written in Net Express Cobol and precompiled using
oracle 9i compiler. I am trying to deploy these so IIS web server.
The basic architecture is the following:

IIS spawns DLLHost.exe --> calls VB.dll (COM+ Object) --> Cobol.dll.

I have very little/no knowledge of Cobol but need to use this
Cobol.dll as a lot of business logic is written in it.

VB dll is compiled as apartment threaded, multiuse.
Cobol dll is compiled as shared, multithreaded.

Problem:
When servicing one request from a browser, everything seems to work
fine. But when I issue two or more request concurrently or very close
to each other, I get error message "error '800706be'" Which in
Microsoft world translates to "Procedure call failed." Can someone
enlighten me as to what is going on here? I had thought that DLLHost
would have a separate copy of Cobol.dll for each request coming in.
But it seems as though it only keeps on copy to service requests. So
I suspect this is a cobol dll compilation issue. But I am at loss;
agin no knowledge of COBOL!

As I need to get this completed SOON I would appreciate ANY
pointers/help/suggestion with this matter.
Thank you
SB
Peter E. C. Dashwood

2004-03-26, 11:00 pm

orzo617@hotmail.com (sb) wrote in message news:<e66a875b.0403201400.5c5ee637@posting.google.com>...
> Hello,
>
> I have Cobol Dlls written in Net Express Cobol and precompiled using
> oracle 9i compiler. I am trying to deploy these so IIS web server.
> The basic architecture is the following:
>
> IIS spawns DLLHost.exe --> calls VB.dll (COM+ Object) --> Cobol.dll.
>
> I have very little/no knowledge of Cobol but need to use this
> Cobol.dll as a lot of business logic is written in it.
>
> VB dll is compiled as apartment threaded, multiuse.
> Cobol dll is compiled as shared, multithreaded.
>
> Problem:
> When servicing one request from a browser, everything seems to work
> fine. But when I issue two or more request concurrently or very close
> to each other, I get error message "error '800706be'" Which in
> Microsoft world translates to "Procedure call failed." Can someone
> enlighten me as to what is going on here?


There is a whole lot of stuff you haven't mentioned.

Is this running as CGI or ASAPI code on IIS? (CGI is not
multi-threaded, no matter how you compile it...)

Are you using MTS to handle the database COMMIT and ROLLBACK? (if you
are, you need a transaction context as well as an object context; if
you're not, you may be in trouble with synchronising).

What settings do you have in component services for the COM+
component?Try "REQUIRES New transaction". If this fails, experiment
with the other settings for this parameter.

> I had thought that DLLHost
> would have a separate copy of Cobol.dll for each request coming in.


No. But if it has the right transaction and object contexts it can
behave as though it does. It looks as though the COBOL .dll is not a
COM server in its own right, but is simply called from the VB COM
server. This is fraught. No new instances can be instantiated and it
is little wonder you are having trouble when you try concurrent
threads. The VB COM+ server needs to get a new instance of the COBOL
..dll each time it (VB) is instantiated. It can only do this if the
COBOL .dll is also a COM server (or it is able to multiply instantiate
the object context it is running in). If the DB access is carried out
in the COBOL .dll, don't be surprised if everything grinds to a halt.

The problem is not with compile options, it is with design.

> But it seems as though it only keeps on copy to service requests. So
> I suspect this is a cobol dll compilation issue. But I am at loss;
> agin no knowledge of COBOL!
>


Your best chance of a quick fix is to tweak DLLHOST.EXE, using the
component services on the server. In particular, see if you can get
the VB COM+ server to run in a MTS environment, and try different
settings of the transaction support parameter for the COM+ server.

The real solution is to rebuild (not re-compile) the COBOL application
so it is a true COM+ server. Then VB can instantiate it any time it
needs to.

I have had some very painful experience implementing COM+ with IIS and
the real solution is to make COBOL another COM+ server just like
everything else. Once you do this, it works beautifully. Both IIS and
COM+ are good technologies. I don't know how MF supports the building
of COM servers in COBOL, as I use Fujitsu, but I should think there
will be equivalent functionality.

There is not enough hard information here to properly diagnose your
problem, but on the evidence, it would seem that a standard COBOL .dll
is being used with an OO COM+ component written in VB. This is like
tying an anchor to a cat and wondering why it can't get over the wall.
The COBOL needs to be OO and wrapped as a standard COM server.
Specifying "multithreading" at compile time is not enough in and of
itself, to get multiple instances. Without this capability, your
application will only ever be good for one thread.

Hope this helps.

I am no longer frequenting CLC (I look in occasionally) but would be
interested to hear how you get on.

Pete.

> As I need to get this completed SOON I would appreciate ANY
> pointers/help/suggestion with this matter.
> Thank you
> SB

Michael Wojcik

2004-03-26, 11:00 pm


In article <b3638c46.0403210635.59a62084@posting.google.com>, dashwood@enternet.co.nz (Peter E. C. Dashwood) writes:
> orzo617@hotmail.com (sb) wrote in message news:<e66a875b.0403201400.5c5ee637@posting.google.com>...
>
> Is this running as CGI or ASAPI code on IIS? (CGI is not
> multi-threaded, no matter how you compile it...)


It's running under DLLHost.exe, thus it's ISAPI. (We could draw the
same conclusion from the fact that there's no application .exe
involved - all the application code is in DLLs.)

Offhand, I'd suggest checking the reentrancy model the COBOL code was
compiled in. In MF COBOL, thread-safe modules can be compiled with
one of three compiler directives: REENTRANT(1), REENTRANT(2), or
SERIAL.

REENTRANT(1) separates compiler-generated storage areas by thread,
but working-storage, FDs, etc are shared across threads, and the
program must serialize access to them manually. This is the
directive to use for a threading model which is similar to the shared
heap / private stack one typically used with C-like languages.

REENTRANT(2) makes all non-external user data per-thread. In effect,
modules compiled with REENTRANT(2) are unaware of threading; their
data is private.

SERIAL allows only one thread to be in the module at a time; the
compiler inserts a mutex around the entire module.

I note that the NX4 documentation recommends REENTRANT(2) for ISAPI
modules.

This seems like a question that's best answered by the Net Express
documentation, in fact. There's a whole chapter on writing ISAPI
modules, and IIRC a tutorial on it as well.

--
Michael Wojcik michael.wojcik@microfocus.com

The antics which have been drawn together in this book are huddled here
for mutual protection like sheep. If they had half a wit apiece each
would bound off in many directions, to unsimplify the target.
-- Walt Kelly
sb

2004-03-26, 11:00 pm

mwojcik@newsguy.com (Michael Wojcik) wrote in message news:<c3mv4801opb@enews1.newsguy.com>...
> In article <b3638c46.0403210635.59a62084@posting.google.com>, dashwood@enternet.co.nz (Peter E. C. Dashwood) writes:
>
> It's running under DLLHost.exe, thus it's ISAPI. (We could draw the
> same conclusion from the fact that there's no application .exe
> involved - all the application code is in DLLs.)
>
> Offhand, I'd suggest checking the reentrancy model the COBOL code was
> compiled in. In MF COBOL, thread-safe modules can be compiled with
> one of three compiler directives: REENTRANT(1), REENTRANT(2), or
> SERIAL.
>
> REENTRANT(1) separates compiler-generated storage areas by thread,
> but working-storage, FDs, etc are shared across threads, and the
> program must serialize access to them manually. This is the
> directive to use for a threading model which is similar to the shared
> heap / private stack one typically used with C-like languages.
>
> REENTRANT(2) makes all non-external user data per-thread. In effect,
> modules compiled with REENTRANT(2) are unaware of threading; their
> data is private.
>
> SERIAL allows only one thread to be in the module at a time; the
> compiler inserts a mutex around the entire module.
>
> I note that the NX4 documentation recommends REENTRANT(2) for ISAPI
> modules.
>
> This seems like a question that's best answered by the Net Express
> documentation, in fact. There's a whole chapter on writing ISAPI
> modules, and IIRC a tutorial on it as well.


Yes. Thank You for answering on by behalf. Indeed, I have looked
into
REENTRANT(1), REENTRANT(2) directives. But it turns out (as per
advice from someone at Microfocus) that REENTRANT(2) clause "can not
be used with procedure division overlays; SECTIONS;" That I need to
use the NOSEG clause. Which I tried without success.

I have looked at some Cobol documentation. Even considered the
Internet Application Wizard. This wizard can take a legacy Cobol
source and convert it to appropriate Web Pages. But apparently, that
version of Application Wizard does not like Indexed Fields. I was not
able to determine which version I need. Currently I am using Net
Express version 3.1. I am not able to find any discussion on Micro
Focus about Indexed Fields problem with this wizard.

Any ideas/pointers would be much appreciated.
SB
Peter E. C. Dashwood

2004-03-26, 11:00 pm

mwojcik@newsguy.com (Michael Wojcik) wrote in message news:<c3mv4801opb@enews1.newsguy.com>...
> In article <b3638c46.0403210635.59a62084@posting.google.com>, dashwood@enternet.co.nz (Peter E. C. Dashwood) writes:
>
> It's running under DLLHost.exe, thus it's ISAPI. (We could draw the
> same conclusion from the fact that there's no application .exe
> involved - all the application code is in DLLs.)


Hmmm...that's interesting, Michael. I have CGI code that also invokes
COM+ components. DLLHost hosts the process but it is NOT ISAPI. I
would need to convert my CGI apps to ISAPI if I wanted to use ISAPI.

Maybe it runs in ISAPI as a single thread and I am just not aware of
it. Are you sure that DLLHost ONLY runs as a multithreaded ISAPI app.?


>
> Offhand, I'd suggest checking the reentrancy model the COBOL code was
> compiled in. In MF COBOL, thread-safe modules can be compiled with
> one of three compiler directives: REENTRANT(1), REENTRANT(2), or
> SERIAL.
>
> REENTRANT(1) separates compiler-generated storage areas by thread,
> but working-storage, FDs, etc are shared across threads, and the
> program must serialize access to them manually. This is the
> directive to use for a threading model which is similar to the shared
> heap / private stack one typically used with C-like languages.
>
> REENTRANT(2) makes all non-external user data per-thread. In effect,
> modules compiled with REENTRANT(2) are unaware of threading; their
> data is private.
>


This sounds like the right stuff.


> SERIAL allows only one thread to be in the module at a time; the
> compiler inserts a mutex around the entire module.
>
> I note that the NX4 documentation recommends REENTRANT(2) for ISAPI
> modules.
>


Yes, that's what I would have expected.

> This seems like a question that's best answered by the Net Express
> documentation, in fact. There's a whole chapter on writing ISAPI
> modules, and IIRC a tutorial on it as well.


But maybe he's posting here because he just doesn't have time to do a
crash course in MF ISAPI...?

It looks like RENTRANT(2) could be a good option.

Pete.
Michael Wojcik

2004-03-26, 11:00 pm


In article <b3638c46.0403222314.3f3294dc@posting.google.com>, dashwood@enternet.co.nz (Peter E. C. Dashwood) writes:
> mwojcik@newsguy.com (Michael Wojcik) wrote in message news:<c3mv4801opb@enews1.newsguy.com>...
>
> Hmmm...that's interesting, Michael. I have CGI code that also invokes
> COM+ components. DLLHost hosts the process but it is NOT ISAPI. I
> would need to convert my CGI apps to ISAPI if I wanted to use ISAPI.


Hmm. I think I just wasn't sufficiently specific, but it's possible
I'm unaware of some additional weird pseudo-CGI facility IIS supports.

CGI is a facility for an HTTP server to run an external program to
process an HTTP request and generate the response (more or less -
except for NPH mode, the CGI program actually generates the HTTP
content-body and some of the HTTP headers, but not the entire
response). CGI/1.1 (which is just a draft anyway; there is no
CGI specification, technically speaking) does allow the CGI "script"
to be within the server process rather than external, but I wasn't
aware that IIS supported that. I just checked the MSDN Library I
have installed and it claims that IIS-hosted CGI scripts are in
fact separate programs (but it's somewhat out of date because I
haven't been able to move to VS.NET yet, and newer versions of the
Library aren't compatible with earlier versions of VS).

So for the moment I'm assuming that IIS only supports CGI scripts
that are in fact external programs.

Given that, if the OP's *entire* application is a DLL running under
DLLHost, it must not be CGI. For CGI, they'd need *some* executable
piece that was executed by IIS for each request.

Now, it's certainly possible to have CGI scripts that invoke COM+
components, and those components may very well run under DLLHost.exe
(the system surrogate process for in-process COM components). But
I don't believe DLLHost.exe can itself serve as a CGI script; for
that to work, DLLHost.exe would need to support the CGI interface,
which is orthogonal to its actual job of hosting COM+ components.

Of course, as I said, I could be unaware of new IIS features for
supporting the CGI interface to "scripts" that aren't separate
executables.

--
Michael Wojcik michael.wojcik@microfocus.com

Thanatos, thanatos! The labourer, dropping his lever,
Hides a black letter close to his heart and goes,
Thanatos, thanatos, home for the day and for ever. -- George Barker
Michael Wojcik

2004-03-26, 11:00 pm


In article <e66a875b.0403221232.689eb0a6@posting.google.com>, orzo617@hotmail.com (sb) writes:
> mwojcik@newsguy.com (Michael Wojcik) wrote in message news:<c3mv4801opb@enews1.newsguy.com>...
>
> Yes. Thank You for answering on by behalf. Indeed, I have looked into
> REENTRANT(1), REENTRANT(2) directives. But it turns out (as per
> advice from someone at Microfocus) that REENTRANT(2) clause "can not
> be used with procedure division overlays; SECTIONS;" That I need to
> use the NOSEG clause. Which I tried without success.


You lost me. You're using segmentation in this COBOL DLL (that is, it
has non-zero segment numbers specified after SECTION word)? Why?

I wasn't aware that segmentation couldn't be used with REENTRANT(2),
but it doesn't surprise me.

In any event, your module needs to be either REENTRANT(1) or
REENTRANT(2) (or perhaps SERIAL), regardless of what other options
you use, to operate correctly in a multithreaded environment. And
I'd definitely recommend getting rid of segmentation; it might be
possible to get that working in this environment, but it's a
tremendous complication.

--
Michael Wojcik michael.wojcik@microfocus.com

Pocket #9: A complete "artificial glen" with rocks, and artificial moon,
and forester's station. Excellent for achieving the effect of the
sublime without going out-of-doors. -- Joe Green
Chris Glazier

2004-03-29, 2:30 pm

orzo617@hotmail.com (sb) wrote in message news:<e66a875b.0403241109.17adf59b@posting.google.com>...
> dashwood@enternet.co.nz (Peter E. C. Dashwood) wrote in message news:<b3638c46.0403210635.59a62084@posting.google.com>...
>
>
> Pete,
>
> Thank you for you suggestions with this matter. I realize now I may
> have to go the OO Cobol route. But still need to find out how to
> pre-compile OO Cobol with Oracle Precompiler.
>
> Saurabh.


Just a few more tidbits of information regarding the problem that you
are experiencing.

One thing that you don't really mention is, at what point during the
execution of your application is the error message being displayed? Is
it when the VB .DLL is being called or when the COBOL .DLL is being
called, or some other point altogether?

If you wait for the first request to complete and then wait a few
seconds before issuing another request does it work correctly?

Your .DLL needs to be compiled with REENTRANT"2" and needs to be
linked with the multi-threaded / dynamic shared run-time system.

If you specify REENTRANT"1", then you need to add thread
synchronization code to your program in order to resolve data
contention between multiple threads. This involves a lot of work in
most cases.

Since this .DLL is not actually an ISAPI application itself but is
instead called by one then it should not be compiled with the
WEBSERVER"ISAPI" directive on. This directive can only be used for a
main COBOL .DLL which is being loaded directly by IIS.

If you are using embedded SQL statements in your program, then it must
also have the correct SQL directives turned on for compilation. If you
are using Oracle then it can either be setup to use the COBSQL
precompiler, which actually passes control to the Oracle precompiler,
or it can be setup to use OpenESQL which is the Net Express
preprocessor for generating SQL programs to be used with an ODBC
driver.

The COBSQL preprocessor for Oracle will only work with procedural
COBOL code. It will not work if the embedded SQL statements are
present within an OO COBOL program or within a nested program. In this
case the OpenESQL preprocessor must be used.

The alternative to this would be to use the Net Express OO Class
Wizard to generate a wrapper for a COBOL COM object which could then
be instantiated by the VB COM object. The COBOL COM Object could then
make calls to the procedural COBOL programs containing the embedded
SQL statements.

If you are using OpenESQL then you would also need to set the SQL
directive for THREAD=ISOLATE in order for an SQL COBOL program to be
thread-safe at run-time.
sb

2004-03-30, 1:30 pm

chris.glazier@microfocus.com (Chris Glazier) wrote in message news:<260cd566.0403291043.78724c70@posting.google.com>...
> orzo617@hotmail.com (sb) wrote in message news:<e66a875b.0403241109.17adf59b@posting.google.com>...
>
> Just a few more tidbits of information regarding the problem that you
> are experiencing.
>
> One thing that you don't really mention is, at what point during the
> execution of your application is the error message being displayed? Is
> it when the VB .DLL is being called or when the COBOL .DLL is being
> called, or some other point altogether?
>

I believe the error happens at the Cobol.dll.
> If you wait for the first request to complete and then wait a few
> seconds before issuing another request does it work correctly?

Yes, I believe the error happens at the COBOL.dll level because if I
issue one request, then wait for the first reqest to finish before
issuing the second request, everything works fine.
> Your .DLL needs to be compiled with REENTRANT"2" and needs to be
> linked with the multi-threaded / dynamic shared run-time system.

I have added the REENTRANT"2" directive but with no success. This
main Cobol.dll calls other cobol.dlls to do the work. I read
somewhere that "if you call a COBOL routine more than once, the
Working-Storage Section data remains unchanged between call unless you
have canceled the program." (Micro Focus Document: "Web-Enabling COBOL
Applications with Net Express"; Page 4). So I issued an explicit
"cancel <program name>" after every call to sub cobol.dlls. This
still did not solve the problem. Yes, the main Cobol.dll and sub
cobol.dlls are all compiled as shared and multi-threaded. Dynamic
binding box is NOT checked.
> If you specify REENTRANT"1", then you need to add thread
> synchronization code to your program in order to resolve data
> contention between multiple threads. This involves a lot of work in
> most cases.
>
> Since this .DLL is not actually an ISAPI application itself but is
> instead called by one then it should not be compiled with the
> WEBSERVER"ISAPI" directive on. This directive can only be used for a
> main COBOL .DLL which is being loaded directly by IIS.

Yes since this not an ISAPI application (i.e. it does not run under
IIS Context) I do not use this directive.
> If you are using embedded SQL statements in your program, then it must
> also have the correct SQL directives turned on for compilation. If you
> are using Oracle then it can either be setup to use the COBSQL
> precompiler, which actually passes control to the Oracle precompiler,
> or it can be setup to use OpenESQL which is the Net Express
> preprocessor for generating SQL programs to be used with an ODBC
> driver.

I belive that the Cobol.dll compiles fine as the Oracle Precompiler
does not complain.
>
> The COBSQL preprocessor for Oracle will only work with procedural
> COBOL code. It will not work if the embedded SQL statements are
> present within an OO COBOL program or within a nested program. In this
> case the OpenESQL preprocessor must be used.

Thank you I did not know this -- valuable information.

> The alternative to this would be to use the Net Express OO Class
> Wizard to generate a wrapper for a COBOL COM object which could then
> be instantiated by the VB COM object. The COBOL COM Object could then
> make calls to the procedural COBOL programs containing the embedded
> SQL statements.

I lost you here. If i wrap the conventional procedural COBOL program
containing embedded SQL Stmts, can I use the Oracle Precompiler. If I
convert these DLL to COM objects then I can bypass VB.dll altogether
and create an instance of COBOL.Dll from vbscript/ASP. But somewhere
I read that $set ooctrl(+p) directive for object cobol restricts the
number of parameters that can be passed in a function to 34. Is this
correct. If so I would have another potential problem.
> If you are using OpenESQL then you would also need to set the SQL
> directive for THREAD=ISOLATE in order for an SQL COBOL program to be
> thread-safe at run-time.


Thanks
SB
Chris Glazier

2004-04-01, 10:30 am

orzo617@hotmail.com (sb) wrote in message news:<e66a875b.0403300941.1a15b541@posting.google.com>...
> chris.glazier@microfocus.com (Chris Glazier) wrote in message news:<260cd566.0403291043.78724c70@posting.google.com>...
> I believe the error happens at the Cobol.dll.
> Yes, I believe the error happens at the COBOL.dll level because if I
> issue one request, then wait for the first reqest to finish before
> issuing the second request, everything works fine.
> I have added the REENTRANT"2" directive but with no success. This
> main Cobol.dll calls other cobol.dlls to do the work. I read
> somewhere that "if you call a COBOL routine more than once, the
> Working-Storage Section data remains unchanged between call unless you
> have canceled the program." (Micro Focus Document: "Web-Enabling COBOL
> Applications with Net Express"; Page 4). So I issued an explicit
> "cancel <program name>" after every call to sub cobol.dlls. This
> still did not solve the problem. Yes, the main Cobol.dll and sub
> cobol.dlls are all compiled as shared and multi-threaded. Dynamic
> binding box is NOT checked.
> Yes since this not an ISAPI application (i.e. it does not run under
> IIS Context) I do not use this directive.
> I belive that the Cobol.dll compiles fine as the Oracle Precompiler
> does not complain.
> Thank you I did not know this -- valuable information.
>
> I lost you here. If i wrap the conventional procedural COBOL program
> containing embedded SQL Stmts, can I use the Oracle Precompiler. If I
> convert these DLL to COM objects then I can bypass VB.dll altogether
> and create an instance of COBOL.Dll from vbscript/ASP. But somewhere
> I read that $set ooctrl(+p) directive for object cobol restricts the
> number of parameters that can be passed in a function to 34. Is this
> correct. If so I would have another potential problem.
>
> Thanks
> SB


Just to close out this thread, the problem was occuring because the
other .DLLS that were being called by the main COBOL .DLL were NOT
compiled with the REENTRANT"2" directive.

When creating a multi-threaded Net Express COBOL application, then ALL
of the programs within the application need to be compiled with one of
the multi-threaded directives, "SERIAL", REENTRANT"1" or REENTRANT"2".

It is not enough just to link these programs with the multi-threaded
run-time system.

There were also a few matters of CALL-CONVENTION from VB to COBOL and
some .ASP/IIS settings that had to be changed since this application
was not running under COM+, but instead it was handling database
transactions through COMMIT/ROLLBACK statements within the COBOL
programs.

It seems to working fine now...
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com