Super Procs vs Persistent Procs

Posted by ojfoggin on 02-Jul-2009 05:13

I have seen a couple of old threads that have taught me a thing or 2 about the differences and similarities of SPs and PPs.  However, I still hve a couple of questions.

I have recently changed our system so that it will use one AppServer per session.

Before this change an appserver was connected each time data was required from the database.  This meant that any super procedures and persistent procedures were closed down with the AppServer and nothing stayed in the memory for too long.

I have sorted out closing all the persistent procedures (lots of them were left open and relied on the AppServer close to take them with it) so now we don't have any leaks in persistent procedures.

I have recently come across session and procedure super-procedures.

I know that with a PP you have to run a procedure IN the handle of the PP.

With a procedure's SP you can run a procedure without having to name the handle (in the owning procedure).

And with a session's SP you can run a procedure without having to name the handle from any procedure within the session.

However, looking through our code it looks like super procedures are started here and there without any checking to see if they are already running.  Ideally I would want to start the session super procs when the app server connects and then stop them when the appserver disconnects (yes?).

As a work around for now, is there a way to check if a session SP is running before running it again?  That way we can begin to clear up our code bit by bit.

Also, as a bit of diagnostic stuff I printed out a list of all the super procedures for a particular procedure  (this-procedure:super-procedures) and then converted them to names and got this...

libapp/custlib.p has super procs - libapp/eventlib.p,libapp/cashlib.p,libapp/damagelib.p,libapp/credcontlib.p,libapp/commonlib.p,sstock-lib.p,libapp/pdalib.p,chmnlib.p,libapp/ordlib2.p,chmnlib.p,libapp/ordlib1.p,chmnlib.p,sstock-lib.p

A few worrying things here, in that sstocklib.p is on there twice and chmnlib.p is on there three times.  Does this list include session super procedures?  Or are these SPs exclusive to custlib.p?

Lot's of questions and probably a lot more in the future!

Thanks for any help you can provide!

All Replies

Posted by rbf on 02-Jul-2009 05:57

ojfoggin wrote:

I have seen a couple of old threads that have taught me a thing or 2 about the differences and similarities of SPs and PPs.  However, I still hve a couple of questions.

Let's talk about Session Super Procs (SSPs) versus Super Procs (SPs). Both are persistent procedures.

>However, looking through our code it looks like super procedures are started here and there without any checking to see if they are already running.  >Ideally I would want to start the session super procs when the app server connects and then stop them when the appserver disconnects (yes?).

No, ideally you would start SSPs when the AppServer starts. It is the Advanced Features Startup property.

>As a work around for now, is there a way to check if a session SP is running before running it again?  That way we can begin to clear up our code bit by bit.

That does not sound like a good idea. Switching from SPs to SSPs generally requires redesign. You have to ensure that your SSPs do not leave any data behind from a previous call, in other words, they have to be made stateless. Your old SPs are most likely stateful.

>Also, as a bit of diagnostic stuff I printed out a list of all the super procedures for a particular procedure  (this-procedure:super-procedures) and then converted them to names and got this...

>libapp/custlib.p has super procs - libapp/eventlib.p,libapp/cashlib.p,libapp/damagelib.p,libapp/credcontlib.p,libapp/commonlib.p,sstock-lib.p,libapp/pdalib.p,chmnlib.p,libapp/ordlib2.p,chmnlib.p,libapp/ordlib1.p,chmnlib.p,sstock-lib.p

>A few worrying things here, in that sstocklib.p is on there twice and chmnlib.p is on there three times.  Does this list include session super procedures?  Or are these SPs exclusive to custlib.p?

They are certainly specific to custlib.p, but not necessarily exclusive to custlib.p. But you can query SESSION:SUPER-PROCEDURES to find out which SPs are SSPs.

>Lot's of questions and probably a lot more in the future!

Definitely. It seems you are underestimating the task of switching from stateful to stateless.

Posted by ojfoggin on 02-Jul-2009 07:07

Ever wish you never started something

Thanks for the help!  I am beginning to realise just how much I under estimated this "fix".  I now have more of an idea how to go about this next bit so that the set up works.  It still is not ideal but at least it works now and doesn't cause memory leaks.

I think most of the problems I am coming across is the fact that no one has ever looked at the way the system works since we had an "audit" by Progress about 3 years ago.

One of the major problems that was pointed out was the usage of the appserver.  This hasn't been dealt with and has now become very difficult to change.

Similarly there is a table that we use that has an index relating to the RECID of records in another table.  Therefore if we try to export and import it will break the index.

Quite a lot of other stuff too.

Posted by rbf on 02-Jul-2009 07:16

[off topic]

Oliver have you noticed the buttons 'correct' and 'helpful' in this forum?

People that help you appreciate if you use those when appropriate.

Posted by ojfoggin on 02-Jul-2009 07:18

Sorry

I will make sure to use them in the future.

Thanks for the help!

Posted by ojfoggin on 06-Jul-2009 07:06

I've come up to a sticking point with this at the moment.

Now, my understanding (which may not be correct) is that if there is a SSP running on an appserver that you should be able to call any procedure from within the SSP from any other procedure running on the AppServer.

i.e. If I have ...

RUN MySuper.p PERSISTENT SET lh-handle.

SESSION:ADD-SUPER-PROCEDURE(lh-handle),

(and MySuper.p contains a proc called GetCustomer)

Then I should be able to say...

RUN GetCustomer(output lc-name).

from any other procedure on the AppServer.  This however, seems to be failing.

I am definitely running the correct code as I have output messages telling me so but when I try to run a procedure from within a SSP it tells me...

"** "credcont-AnyAlerts" was not found. (293)"

(credcont-AnyAlerts is in a SSP and the SSP is definitely there as I message all the SSPs out before it hit's that line and it's in there.)

Posted by rbf on 06-Jul-2009 07:40

Hi Oliver,

Your understanding is correct. However your syntax is not.

When you code

RUN GetCustomer(output lc-name).

The compiler is going to expect the program on disk.

Instead, code

RUN GetCustomer(output lc-name) IN THIS-PROCEDURE.

Posted by Admin on 06-Jul-2009 07:45

RUN GetCustomer(output lc-name).

The compiler is going to expect the program on disk.

Instead, code

RUN GetCustomer(output lc-name) IN THIS-PROCEDURE.

Hi Peter,

since when is it required to specify RUN ... IN THIS-PROCEDURE. The IN THIS-PROCEDURE is optional. It won't hurt, but it shouldn't be required. I'd rather add spaces before the "(".

RUN

  { intern-proc-name | VALUE ( intern-expression) } 

  [ IN proc-handle ]

  [ ASYNCHRONOUS

       [ SET async-request-handle ]

       [ EVENT-PROCEDURE event-internal-procedure

           [ IN procedure-context ] ]

  ]

  [ ( parameter [ , parameter ] ... ) ]

  [ NO-ERROR ]


The IN prc-handle is optional.

Posted by ojfoggin on 06-Jul-2009 07:51

Thank you for both your replies.

I seem to have found the reason it is not finding the Session procedures.

For soem reason they seem to be getting stopped.

I have not had chance to properly loko into this yet but when it fails the Session:super-procedures function returns "".

Thanks for the help.

Oliver

Posted by rbf on 06-Jul-2009 08:34

Hi Oliver,

You tricked us both!

Mike is right that IN THIS-PROCEDURE is optional, it just excludes Progress to check on disk. Somewhere in the docs you should be able to find the priority sequence, but obviously it is good practice to always add IN THIS-PROCEDURE if you want to run an internal procedure since you don't want Progress to check the disk in that case.

The space that Mike recommends is also optional, but also good practice.

-peter

Posted by Stefan Drissen on 06-Jul-2009 17:46

> Mike is right that IN THIS-PROCEDURE is optional, it just excludes Progress to check on disk.

Where do you get this from? As the manual, quoted by Mike, states when left out Progress fills it out for you. I would expect this behavior to take place at compile time. I see no room for magic disk checks being skipped.

> Somewhere in the docs you should be able to find the priority sequence, but obviously it is good practice to always add IN THIS-PROCEDURE if you want to run an internal procedure since you don't want Progress to check the disk in that case.

There is nothing 'obviously good practice' about typing extra stuff that has no effect (until you come up with the magic disk check goods). The IN THIS-PROCEDURE is even worse in this case is that it is not harmless like typing initial values that are the default anyway, but when simply reading it it lets you believe that the procedure is going to be in this procedure, which it does not need to be, it can be in one of the supers.

> The space that Mike recommends is also optional, but also good practice.

Mikes space is obivously good practice since it improves legibility.

Posted by rbf on 07-Jul-2009 02:29

14941 wrote:

> Mike is right that IN THIS-PROCEDURE is optional, it just excludes Progress to check on disk.

Where do you get this from? As the manual, quoted by Mike, states when left out Progress fills it out for you. I would expect this behavior to take place at compile time. I see no room for magic disk checks being skipped.

Here is the quote from the docs:

intern-proc-name
The name of the (local or remote) internal procedure you want to run. The procedure must
be declared in the same procedure file as the RUN statement that calls it unless you specify
the IN proc-handle option or use a super procedure. If you do not specify the IN
proc-handle option and there is no internal procedure declared by the specified name, the
AVM tries to run an external procedure with the specified name.
If the internal procedure
is remote, you must specify the IN proc-handle option to identify the remote persistent
procedure that defines the internal procedure on an AppServer.

> There is nothing 'obviously good practice' about typing extra stuff that has no effect (until you come up with the magic disk check goods).

I believe you stand corrected now.

-peter

Posted by Stefan Drissen on 07-Jul-2009 02:55

Thank you for the pointer on the attempt to read file from disk with the same name as internal procedure. Although logical I did not realize the external run would be attempted.

If I type

RUN dummy.

and 'dummy' does not exist as an internal procedure a check is done to see if file 'dummy' (without any extension) exists as a top level source in the propath. The chance of this happening is zero as far as I'm concerned, so if a disk read does occur this will always result in an error. Perhaps you have other cases where this can be useful.

Adding IN THIS-PROCEDURE to prevent the extra disk read when an error is going to occur anyway is therefore still not good practice.

Regards,

Stefan

Posted by rbf on 07-Jul-2009 03:21

I agree there is no use case for a procedure on disk with the same name as an internal procedure. Although the chances are bigger than you suspect:

If you omit the extension, then the AVM first adds a .r to the name you specify and searches the first directory for an r-code file with
that name. If none is found, then the AVM searches for a source file with no suffix or extension.

Of course a good naming convention could help here.

Having said that, I do find the IN THIS-PROCEDURE phrase useful for readability purposes and should be used at all times to show that the developers means to run an internal rather than an external procedure.

-peter

Posted by Stefan Drissen on 07-Jul-2009 03:44

Before posting I created file dummy.p in the root of the working directory in the propath which is why I mentioned 'must exist without an extension'

RUN dummy. does not find dummy.p or dummy.r.

I think you are confusing the behavior of RUN dummy.p also finding dummy.r

The thing I find obfuscating about IN THIS-PROCEDURE is that the procedure does not need to be IN THIS-PROCEDURE but can also be an internal procedure on the super stack.

I also find reading (and typing) less is more - but on that we can agree to disagree.

Posted by Admin on 07-Jul-2009 04:12

RUN dummy.

should find dummy.r - at least it does on my system - but only when R-Code is available. Other examples:

RUN _ab.

finds %DLC%\gui\_ab.r

RUN adm2/data.

finds %DLC%\gui\adm2\data.r

Posted by jmls on 07-Jul-2009 04:16

A really nasty trick to play is:

RUN SomeProgram.p.

[snip]

lots of lines of code

[snip]

PROCEDURE SomeProgram.p:

do some stuff

END PROCEDURE.

Posted by Admin on 07-Jul-2009 04:18

That's what I call successfully shooting yourself in the foot!

Posted by Stefan Drissen on 07-Jul-2009 04:19

I stand corrected as to the .r running. I had previously checked this by renaming dummy.p to dummy.r - however when actually compiling dummy.p, the real .r is found when running without extension.

Posted by Stefan Drissen on 07-Jul-2009 04:19

Lovely!

Posted by rbf on 07-Jul-2009 04:19

14941 wrote:

Before posting I created file dummy.p in the root of the working directory in the propath which is why I mentioned 'must exist without an extension'

RUN dummy. does not find dummy.p or dummy.r.

I think you are confusing the behavior of RUN dummy.p also finding dummy.r

I am not. The documentation is clear, so the question is only is it a documention error or a bug? I couldn't care less since nobody wants this behavior anyway.

The thing I find obfuscating about IN THIS-PROCEDURE is that the procedure does not need to be IN THIS-PROCEDURE but can also be an internal procedure on the super stack.

I agree that this is a result of the poor syntax of the RUN statement where you cannot otherwise explicitely state that you want to run either an internal or an external procedure. Before SPs were introduced IN THIS-PROCEDURE covered this situation, but now INTERNALLY or RUN INTERNAL would be better syntax.

I also find reading (and typing) less is more - but on that we can agree to disagree.

Indeed.

Posted by jmls on 07-Jul-2009 04:24

it can get better:

RUN SomeProgram.p.

[snip]
lots of lines of code
[snip]

PROCEDURE SomeProgram.p:
do some stuff, like create a record, or some other funky nastiness
RUN SomeProgram.r. /* run the external program. Now, someone looking at the code of SomeProgram.p
                       cannot figure out where / how this funky nastiness happens */
END PROCEDURE.

Yeah, I have come across this during a consulting gig. The programmer did not understand why I was a little .. um ... erm ... ___annoyed___

This thread is closed