Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Interesting F$GETQUI restriction

 
SOLVED
Go to solution
EdgarZamora_1
Respected Contributor

Interesting F$GETQUI restriction

I'm bored today so I thought I'd start a thread. Discovered something interesting the other day while trying to debug a DCL procedure that looped through all the entries in a specified print queue using wildcarded F$GETQUI. Pretty standard F$GETQUI stuff... only sometimes it would operate on the entries twice! Most of the time the procedure worked (deleting all entries, or holding all entries, etc) but maybe 1 percent of the time it would go through all entries twice!

I decided to read the F$GETQUI documentation (what a novel idea!) and found this interesting tidbit (DCLI-426):

-----------------------------------Restriction--------------------------------------
The GQC that is saved for wildcarded F$GETQUI calls is destroyed if you run any DCL queue-related command, such as SHOW QUEUE or SHOW
ENTRY. To avoid this problem, use the SPAWN command to create a new process in which to run the DCL commands.

Whoa! Timeout... I've seen so many examples and pieces of code that looped through queue entries and none ever spawned a subprocess before "operating" on the current entry. Even Bruce Claremont's sample code in his article in the OpenVMS Technical Journal volume 11 (F$GETQUI To The Rescue) doesn't.

Bottom line... I modified my script to open a temp file and write out the DCL queue commands I wanted to execute (mostly SET ENTRY commands) then after I had finished looping through all the F$GETQUI entries, I closed the temp file and SPAWNed a subprocess to execute the commands. I didn't want to do a SPAWN for every entry (which would've been the easier thing to do) because there could be hundreds of entries in the queue and I didn't want to spam spawning subprocesses. Now my procedure works 100% of the time.

How many of you knew this restriction?
10 REPLIES 10
Jan van den Ende
Honored Contributor

Re: Interesting F$GETQUI restriction

Edgar,

I ran into it a couple of years ago, but I did not feel I truely mastered f$getqui, and I found that bit of docu then.
So, I blamed my own lack of knowledge, and took the indicated action.
Interestingly, I -- never -- (yet!) had that issue with SET ENTRY, so I did nothing special for those.

You make me wonder now: is this a SHOW-only issue, or have I been "lucky" sofar?

It seems reasonable, that any command that somehow scans queue-related objects DOES need context.
In hindsight it --might-- have been preferable to use a F$GETQUI-specific context specifier (or maybe something like the stream-identifier for f$search) but I do not even KNOW if that would be possible.

But - what you get IS the documented behavior.. :-)

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
EdgarZamora_1
Respected Contributor

Re: Interesting F$GETQUI restriction

I think if one is deleting entries it's not a problem (because the entry is gone after being deleted) but other operations may be affected. I don't do any SHOW ENTRY in my script. Where I discovered it was when I was doing SET ENTRY /HOLD (and /NOHOLD).
EdgarZamora_1
Respected Contributor

Re: Interesting F$GETQUI restriction

Same here Jan! After I first read the restriction I did say to myself... ok there's gotta be a context specifier or stream id and I looked for it... no such luck. It would be nice!
Jan van den Ende
Honored Contributor

Re: Interesting F$GETQUI restriction

Edgar,

>>>
Where I discovered it was when I was doing SET ENTRY /HOLD (and /NOHOLD).
<<<

I cannot recall any programmed SET ENTRYs.
So, it appears I escaped by pure luck!

Be sure I will remember this one! Thanks!

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Jess Goodman
Esteemed Contributor
Solution

Re: Interesting F$GETQUI restriction

There is a default wildcard context for SYS$GETQUI although you can ask SYS$GETQUI to use a different wildcard context by passing it a context variable initialized to -1 on the first wildcard call.

F$GETQUI and (apparently) all the DCL queue related commands all use the default wildcard context. This context is reset if SYS$GETQUI is called with a different object-id, even when there is no wildcard involved in the new SYS$GETQUI call.

Many DCL queue related commands will call SYS$GETQUI at least once, if for no other reason then to use its TRANSLATE_QUEUE function which only has one item code, QUEUE_NAME, and is used to interatively translate logical names - not just for queues but also for forms and characteristics.

So if you are in the middle of a wildcard F$GETQUI loop even this call would destroy the context:
$ NAME = F$GETQUI("TRANSLATE_QUEUE","QUEUE_NAME", "SYS$PRINT")
despite the fact that no wildcard is involved and the "WILDCARD" keyword is not even allowed as a flag argument with TRANSLATE_QUEUE.

Years ago I got tired of writing lots of different command files that used a wildcard F$GETQUI loop to find queues that I wanted to execute commands on (START, STOP, SET) since it was a pain to work-around this restriction. I also had a lot of command files that used F$GETQUI as a selection filter for SHOW QUEUE commands.

Eventually I wrote one command file that can be used for any DCL command line that takes a queue name. Over time I made it more robust and added lots of features. It is attached to this post.

---------------------------------------------
QUEUE_COMMANDS executes any valid DCL command line that uses a queue name. Instead of a single queue name you can use a list of names with wildcards.

Qualifiers not in below lists are passed on so must be valid for the verb.
These three SHOW QUEUE selection qualifiers are supported for any command:
/BATCH Batch queues only.
/DEVICE[=type] Symbiont [type] queues only.
/GENERIC Generic and logical queues (blame DCL for the combo).

These qualifiers can also be used on any command line, including SHOW QUEUE:
/NOGENERIC Execution queues (ignores generic and logical queues).
/[NO]AUTOSTART Queues [not] set to autostart on one or more nodes.
/NODE[=node_name] Queues that execute on given node. "*" and "" allowed.
/STOPPED Queues that are currently stopped.
/CONFIRM Prompt for confirmation before executing commands.
/DISPLAY Display the commands as they are being executed.
/NOEXECUTE Do not execute the commands but do display them.
/NOON Continue with next matching queue if an error occurs.

Note there are two special /NODE= cases and useful combinations of the above:
/NODE=* Execution and logical queues (no true generic queues).
/GENERIC /NODE=* Logical queues only.
/GENERIC /NODE="" True generic queues only (i.e. no logical queues).

Examples:

$ QC :== @QUEUE_COMMANDS.COM
$ QC SHOW QUEUE /ALL/DEVICE/NOGENERIC
$ QC STOP/QUEUE/NEXT * /NODE=ADAM/NOAUTOSTART/DISPLAY
$ QC START/QUEUE /BATCH/NODE/STOPPED *
$ QC SET QUEUE /CLOSE *VAX* /CONFIRM
$ QC PRINT REPORT.TXT /QUEUE=(SYS$PRINT,SYS$PRINT2) /NOTIFY
$ QC @DELETE_OLD_JOBS * -0-04:00 /DEVICE=(PRINTER,TERMINAL)
I have one, but it's personal.
Ian Miller.
Honored Contributor

Re: Interesting F$GETQUI restriction

Jess, perhaps you can submit this procedure to dcl.openvms.org so more people can find it.
____________________
Purely Personal Opinion
Hoff
Honored Contributor

Re: Interesting F$GETQUI restriction

I was responsible for propagating some parts of the documentation related to that particular queue behavior.

I can't speak to the specific queue commands. MAIL was one of the cases I received trouble reports on, and that triggered some documentation updates. IIRC, it was the PRINT command within MAIL that was blowing the f$getqui context freeze, in the particular case.
John Gillings
Honored Contributor

Re: Interesting F$GETQUI restriction

Edgar,

I've certainly been bitten by this before! The reason F$GETQUI is so troublesome is the context is quite complex, but has no visibiliy at all. Too many things can potentially change it. In addition to SET and SHOW QUEUE commands, there's MAIL, as Hoff has mentioned, and I'd also add various TCPIP commands.


Here's a piece of a procedure I use to find and report on retained jobs, or those where the scheduled procedure has been superceeded. Note the comment:


$ IF e.NES.LastEntry
$ THEN
$ WRITE SYS$OUTPUT ""
$! Use SPAWN for the SHOW ENTRY to retain queue
$! context in this process.
$ SPAWN/NOLOG SHOW ENTRY/FULL 'e'
$ WRITE SYS$OUTPUT ""
$ LastEntry=e


>I modified my script to open a temp file
>and write out the DCL queue commands I
>wanted to execute (mostly SET ENTRY
>commands) then after I had finished
>looping through all the F$GETQUI entries,
>I closed the temp file and SPAWNed a
>subprocess to execute the commands. I
>didn't want to do a SPAWN for every entry

I hate temporary files. An alternative is be to write the commands to SYS$OUTPUT, then:

$ PIPE @your-procedure | @sys$pipe

A crucible of informative mistakes
Derek Garson
Frequent Advisor

Re: Interesting F$GETQUI restriction

Seems nuts to me. Yes, my command procedures are broken too.

Looks like the $GETQUI doco isn't 100% either.

"The context is marked with the callerâ s mode (user, supervisor, executive, or kernel). Any attempt to use that context in successive calls is checked and no call from a mode outside the recorded mode is allowed access."

Maybe that doesn't apply to the default context.

I can't see any reason why the various DCL commands shouldn't use a unique context. That would avoid most of the problem.
Jess Goodman
Esteemed Contributor

Re: Interesting F$GETQUI restriction

Edgar,

I re-read your original post and did some tests. It turns out that the problem you observed is not caused by the process GQC being destroyed by a SET ENTRY command.

The actual problem is that a DISPLAY_JOB F$GETQUI loop can get confused and does not know when it has returned all the jobs in a queue, if the order of the jobs in the queue changes during the loop.

Here is a command file that demonstrates your problem. Every time it is run it will loop through the queue's entries twice because the SET ENTRY/HOLD commands have the effect of reversing the order of the jobs in the queue.

$ SAY := WRITE SYS$OUTPUT
$ INITIALIZE /QUEUE /BATCH TESTQ
$ SUBMIT LOGIN.COM /NOLOG /QUEUE=TESTQ
$ SUBMIT LOGIN.COM /NOLOG /QUEUE=TESTQ
$ SUBMIT LOGIN.COM /NOLOG /QUEUE=TESTQ
$ SHOW QUEUE TESTQ
$ DUMMY = F$GETQUI("")
$!
$ SAY F$GETQUI("DISPLAY_QUEUE","QUEUE_NAME","TESTQ","WILDCARD")
$JOB_LOOP:
$ ENTRY = F$GETQUI("DISPLAY_JOB","ENTRY_NUMBER")
$ IF (ENTRY .EQS. "") THEN GOTO END
$ SAY "Next entry is: ",ENTRY
$ SET ENTRY/HOLD 'ENTRY'
$ GOTO JOB_LOOP
$!
$END:
$ SAY "No more entries"
$ DUMMY = F$GETQUI("")
$ DELETE/QUEUE TESTQ
$ EXIT

After running it the way it is above, edit the command file and insert "SPAWN" before the SET ENTRY command. It will still loop twice, as it will if you make the SET ENTRY line:
$ PIPE SAY "SET ENTRY/HOLD ''ENTRY'" | @SYS$PIPE

In fact if you manually execute this command file one line at a time, you can even execute the SET ENTRY commands from a different interactive process on another node! It will still loop twice.

I played some games with SET ENTRY /PRIORITY so that the job order would keep changing, and I was able to get the three entries to loop 86 times.

It's not clear to me what the correct way to handle jobs changing order during a F$GETQUI job loop would be, so I will avoid calling this a VMS bug, but it is certainly an unexpected result.

I have one, but it's personal.