Database ALIAS trouble.

ron

Member
Hi - I hope someone can help me.

I've used with the _Lock and other VST tables before without trouble - but I'm having a problem in a multi-DB environment using DICTDB. I have used DICTDB before - but not with VSTs.

I'm testing on a 9.1D environment (old, yes, but that's what I've been given - they're in the process of changing to 10.2).

The program I'm testing is a bit big, so I've extracted the problematic piece as follows:

Code:
[FONT=courier new]DEF VAR db              AS CHAR    NO-UNDO.
DEF VAR i               AS INT     NO-UNDO.[/FONT]
[FONT=courier new]DEF STREAM logdata.[/FONT]
[FONT=courier new]OUTPUT STREAM logdata TO VALUE("/tmp/CL.log") UNBUFFERED.[/FONT]
[FONT=courier new]REPEAT:
  IF SEARCH("/tmp/stop") <> ? THEN
    LEAVE.
  DO i = 1 TO 3:
    ASSIGN db = LDBNAME(i).
    IF db = ? THEN LEAVE.
    CREATE ALIAS DICTDB FOR DATABASE VALUE(db).
    /* Scan all locks for this DB */
[COLOR=#ff0000]RUN logit(INPUT "Scanning locks for DB: " + TRIM(STRING(db)) ).
[/COLOR]  FOR EACH DICTDB._Lock NO-LOCK:
      IF DICTDB._Lock._Lock-Table = ?
      OR DICTDB._Lock._Lock-Usr   = ? THEN LEAVE.
[COLOR=#ff0000]RUN logit(INPUT "Found lock ID: " + TRIM(STRING(DICTDB._Lock._Lock-Id)) ).
[/COLOR]  END.
  END.
  PAUSE 20.
END.[/FONT]
[FONT=courier new]PROCEDURE logit.
  DEFINE INPUT PARAMETER log-text AS CHAR FORMAT "x(90)".
  DEF VAR msg  AS CHAR FORMAT "x(99)".
  ASSIGN msg = "CL: " + STRING(time,"HH:MM:SS") + ": " + log-text + ".".
  PUT STREAM logdata UNFORMATTED RIGHT-TRIM(msg) SKIP.
END PROCEDURE.
[/FONT]

When the program runs it is connected to three DBs: "TranMon", "dbase" and "dldb" (in that order).

If I run the test program with no records locked, the log shows:

CL: 17:20:17: Scanning locks for DB: dbase.
CL: 17:20:37: Scanning locks for DB: TranMon.
CL: 17:20:37: Scanning locks for DB: dldb.
CL: 17:20:37: Scanning locks for DB: dbase.
CL: 17:20:57: Scanning locks for DB: TranMon.
CL: 17:20:57: Scanning locks for DB: dldb.
CL: 17:20:57: Scanning locks for DB: dbase.

... which is what I expect.

But when I start locking records in another session - it ONLY displays that it sees a lock when I lock a record for the first database (TranMon), like this:

CL: 17:21:17: Scanning locks for DB: TranMon.
CL: 17:21:17: Found lock ID: 1.
CL: 17:21:17: Scanning locks for DB: dldb.
CL: 17:21:17: Found lock ID: 1.
CL: 17:21:17: Scanning locks for DB: dbase.
CL: 17:21:17: Found lock ID: 1.

However - it is reporting that is sees the lock for each DB - when in fact a record is only locked in Tranmon. If there are no records locked at all in TranMon - but records are locked in either or both of the other DBs - nothing is shown.

Either there is a bug in the code that I can't see - or DICTDB doesn't work for VSTs as I expect.

Can anyone explain my problem? Or, alternatively, explain another way that I can get at the VSTs of multiple databases?

Cheers,
Ron.
 
you need to change the alias in a separate program, changes of the alias does not apply in the same compilation unit :(

Code:
DO i = 1 TO 3:
    ASSIGN db = LDBNAME(i).
    IF db = ? THEN LEAVE.
    CREATE ALIAS DICTDB FOR DATABASE VALUE(db).
    /* Scan all locks for this DB */
    RUN logit(INPUT "Scanning locks for DB: " + TRIM(STRING(db)) ).
    FOR EACH DICTDB._Lock NO-LOCK:

Code:
DO i = 1 TO 3:
    ASSIGN db = LDBNAME(i).
    IF db = ? THEN LEAVE.
    RUN setDictDb.p (db). 
    /* Scan all locks for this DB */
    RUN logit(INPUT "Scanning locks for DB: " + TRIM(STRING(db)) ).
    FOR EACH DICTDB._Lock NO-LOCK:


/* external procedure setDictDb.p */
DEF INPUT PARAM dbName AS CHARACTER NO-UNDO.
CREATE ALIAS DICTDB FOR DATABASE VALUE(dbName).
 
Aha!

Thank you for that. Now that you've pointed it out - I remember that important detail!

Cheers,
Ron.
 
I'm still stuck.

I found and read the Progress doc where it said that an external procedure was needed - and changed the test code accordingly - but the behaviour hasn't changed at all.

The part of the main test procedure is now:

Code:
DO i = 1 TO 3:
  ASSIGN db = LDBNAME(i).
  IF db = ? THEN LEAVE.
[COLOR=#ff0000]RUN /u0/MON/SetDICTDB.p (db).
[/COLOR]/* Scan all locks for this DB */

... and the external procedure (/u0/MON/SetDICTDB.p) is simply:

Code:
DEFINE INPUT PARAMETER db-Name AS CHAR.
CREATE ALIAS DICTDB FOR DATABASE VALUE(db-Name).

(I've used an absolute path just for testing - I'll fix-up the paths when I get it working.)

What else am I doing wrong??

Ron.
 
You need to create the alias in the calling procedure. The target procedure uses the alias name to reference the tables.

Code:
CREATE ALIAS VALUE (T_DB.DB_ALIAS) FOR DATABASE VALUE (T_DB.DB_NAME).
CREATE ALIAS TINYDICT FOR DATABASE VALUE(LDBNAME(i)).
RUN _db_gw.p (OUTPUT gwflag, OUTPUT Fi_Database_Name, OUTPUT db-type).

Code:
DEFINE OUTPUT PARAMETER anygw   AS LOG INITIAL no NO-UNDO.
DEFINE OUTPUT PARAMETER db-name AS CHAR           NO-UNDO.
DEFINE OUTPUT PARAMETER db-type AS CHAR           NO-UNDO.

FOR EACH tinydict._db WHERE tinydict._db._db-name <> ?          AND 
                            tinydict._db._db-type <> "PROGRESS" AND
                            tinydict._db._db-local = no         AND
                            tinydict._db._db-slave = yes:
   ASSIGN anygw = yes
          db-name = db-name + "," + tinydict._db._db-name
          db-type = db-type + "," + tinydict._db._db-type.
END.
/* Remove leading comma */
IF LENGTH(db-name,"CHARACTER") > 0 THEN db-name = SUBSTRING(db-name,2,-1,"CHARACTER").
IF LENGTH(db-type,"CHARACTER") > 0 THEN db-type = SUBSTRING(db-type,2,-1,"CHARACTER").

RETURN.
 
That you very much. That makes sense. Clearly I should have examined the Progress example more carefully.

Cheers,
Ron.
 
Aside from the alias issue...

This little bit of code:
Code:
  FOR EACH DICTDB._Lock NO-LOCK:

is likely to be very problematic if your -L is non-trivial (more than a few thousand) or if you have a lot of locking activity. Queries like against _LOCK this have an unfortunate tendency to never complete. _LOCK isn't really a "table" -- it is a linked list in shared memory and it changes very rapidly -- so rapidly that a FOR EACH cannot keep up.

You are testing _lock-usr and _lock-table inside your loop, which may work, but that is a two-step process and IMHO it would be easy for later code modifcations to muck it up.

The better way to implement queries on _LOCK is:
Code:
  FOR DICTDB._Lock NO-LOCK while _Lock-usr <> ?:
 
Thank you, Tom.

I saw the cautionary remarks about scanning the _Lock table in Dan Foreman's VST book - and the program I've written (not the test one) captures the scan time (with ETIME) so I can see how long it takes when I move this to production. I'll change to use the WHILE statement as you suggest. AAMOF ... the code I used in this case was as per a snip of code in a Progress KB.

Cheers,
Ron.
 
The documentation and the KB are famous for their bad practice examples in a sense that they show the functionality but don't care about good practice and context. But that is IMHO of course.

Heavy Regards, RealHeavyDude.
 
Back
Top