Test to see if buffer exists

DeVNuLL

New Member
I'm trying to write some audit code for an application written in Progress 9.1E/Webspeed 3.1E. I was planning on using table triggers for this code as a 'catch all' but I need to be able to test if a certain buffer has been defined. This buffer will only exist if the user has logged in to the application in question and not connected to the database using client/server.

The code I would imagine would look something like

TRIGGER PROCEDURE FOR WRITE OF sometable new buffer newbuf old buffer oldbuf.

create history.

if <this buffer exists> then
assign history.whodidit = <buffer>.usercode
history.whatdidit = "someapp".

else
assign history.whodidit = userid("dictdb")
history.whatdidit = "dblogin".

Any help would be very much appreciated.
 

RealHeavyDude

Well-Known Member
Where will the buffer be created - in some other procedure?

The buffer you're talking about - is it a dynamic buffer object?

If so you could determine if a specific dynamic buffer object exists in the session by doing a widget tree walk.



HTH, RealHeavyDude.
 

DeVNuLL

New Member
Hi,

the buffer was created by a 'define buffer loginuserdata for userdata' statement. the buffer will contain the user record for the currently logged in user.

Many Thanks
 

RealHeavyDude

Well-Known Member
If I were you I would use a dynamic buffer object.

  • Create the dynamic buffer object in your login procedure.
DEFINE VARIABLE hLoginUserData AS HANDLE NO-UNDO.

CREATE BUFFER hLoginUserData FOR TABLE 'userdata':U.
hLoginUserData:FIND-UNIQUE ( 'WHERE ...', NO-LOCK ).
  • Do a widget-tree walk in your trigger procedure to see if the dynamic buffer object exists in the session.
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.
DEFINE VARIABLE hLoginUserData AS HANDLE NO-UNDO.


ASSIGN hBuffer = SESSION:FIRST-BUFFER.
DO WHILE VALID-HANDLE ( hBuffer ):
/* Got you ... */
IF hBuffer:NAME = 'userdata':U THEN
ASSIGN hLoginUserData = hBuffer.
ASSIGN hBuffer = hBuffer:NEXT-SIBLING.
END.

IF VALID-HANDLE ( hLoginUserData ) THEN DO:
ASSIGN xyz = hLoginUserData:BUFFER-FIELD ( 'usercode':U ):BUFFER-VALUE.
END.

HTH, RealHeavyDude.
 

RealHeavyDude

Well-Known Member
Just to add to it:

If you are not familiar with dynamic objects you should be aware that the 4GL does not take care for them like it does with static objects. That means you are responsible to destroy them ( DELETE OBJECT hXyz ) when you don't need them anymore. Otherwise you might introduce a memory leak into your application ...

Regards, RealHeavyDude.
 

DeVNuLL

New Member
OK I will bear that in mind and run a check of the code to ensure there is a corresponding delete for every object created before it gets put into production.

Thanks again,

Chris.
 

schaapie

Member
Maybe I don't get it, but for the buffer to still exist and be filled, the procedure creating it must still exist (persistent).
Or is the login-procedure always in your stacktrace?

Couldn't you just ask this persistent-procedure the login/audit-name?
 

RealHeavyDude

Well-Known Member
Handle-based dynamic objects are not automatically scoped to the procedure that creates them.

If you don't do anything then these objects are scoped to the session because the default widget-pool is the unnamed widget-pool of the session itself.

What you can do is, on purpose put these objects into a widget-pool to override this behavior (have a look into the source code of any .w file that you have created in the AppBuilder and you will find a CREATE WIDGET-POOL statement nearly at the top of it):

  • As soon as you put a CREATE WIDGET-POOL at the top of a procedure then all handle-based dynamic objects created in the procedure that don't specify otherwise will end up in this unnamed widget-pool scoped to the procedure, and - hence, will be destroyed when the procedure is destroyed.
  • You can also create a named widget-pool that is scoped to a procedure and append the IN WIDGET-POOL 'yourWidgetPool' phrase in the create statement of the handle-based dynamic object.
  • And, you can create a named persistent widget-pool that will always be to the session to make sure these objects live as long as you delete the widget-pool yourself or the session ends ...
Working with WIDGET-POOLs can make you life trickier, but it also can make it easy. IMHO what is missing from this functionality is to get information to a particular widget-pool as to what handle-based objects it contains ... but AFAIK the enhancement request I've entered at Progress for that did not get much attention.


HTH, RealHeavyDude.
 

schaapie

Member
OK, I don't have much experience with widget-pools.
But this is considered "good practise"?
Sounds like "def global shared buffer" to me.
 

RealHeavyDude

Well-Known Member
Defining something as SHARED or GLOBALLY SHARED introduces dependencies between pieces of code and generates intransparancy. That, IMHO, is definately bad practice.

Using dynamic handle-based objects and passing the handle to them around as paramters and group them in widget-pools for management purposes, IMHO, is not bad practice. _BUT_, it is up to you, because virtually every "new" feature or functionality may be misused to mimic old-school programming techniques that are consiered bad practice as of our recent knowledge.

The same is true for the OO enhancenment to the 4GL - just for coding classes instead of procedures it is not necessary to understand OO concepts or following them.

Regards, RealHeavyDude.
 
Top