How to populate/clear a Grid (GC) since C Code

Oskr

Member
Good afternoon, it's been a long while since i was there :D. I need to know how can i populate a Grid Control since a C-function, explicitly not NER... it must be C code... which will be called by a NER function.. maybe an event, whatever. If somebody wants to know why... well... i use to develop DLL's for extending the capabilities of JDE (like executing S.O. commands/processes with ret-val, output, etc; access physical ports like parallel and serial on clients; sending a response to another external application on another machine... etc). Well, this time I'll give support to be able to execute DQL, DML, DDL, PLSQL on Oracle obviously and DQL, DML, DDL, TSQL for another servers in SQLServer (different applications of retail shop) using Named Pipes etc etc etc... but when I receive these large amounts of data i have to put them on the grid immediatly... not waiting a call from a NER function for a single record once, again, again, and so...
With this the developers on the Department won´t be creating tables each time they need an array, and Views with poor or so much limited sql statements (this is annoying for me because I am also the DBA), also they´ll be able to query another kind of DB servers... see? I just need to know this...

Thanks in advance...

(I apologize for the bad writing, this is not my native language).

PD900
Win2k8 Server x64
Oracle Database 11g Release 11.1.0.6.0
 

BBritain

VIP Member
I only know of one person who has done this (Steve Praed) and only one or two others who might. I would love to hear what the gurus have to say about this!
 

craig_welton

Legendary Poster
From what I know, this can only be done with a fat client app. Something like this from a BSFN:
Code:
[SIZE=2]hGrid = GetDlgItem(lpBhvrCom->hDlg, 5001);
[/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]if[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] (hGrid)
{
     jdeGridAddRow(hGrid, lpDS->szDataField1, 1);
}[/SIZE]


The dialog resource Id of the grid control is 5000 + the object ID. In the above case, it's a 1. There are a ton of jdeGrid* functions you can use.

If anyone has a solution for the HTML presentation, that would be great to hear. There are APIs to control the appearance of the web grid, but not to add rows AFAIK.

Craig
 

BOster

Legendary Poster
but when I receive these large amounts of data i have to put them on the grid immediatly... not waiting a call from a NER function for a single record once, again, again, and so...


Not exactly sure what you mean by that, however, I fill grids all the time from C BSFNs and performance is great with multiple BSFN calls to return a single record into the grid. Some variation on the following simple design patter:

Code:
InitFunction
	- run query or do what ever action is needed to get the data.  return handle to the "session" to maintain state.
IterFunction
   - Iterates the result set. one call returns one record.  last call returns flag that end-of-list or data has been reached
   - DS looks like this:
   idSessionHandle
   cEndOfList (1/0 flag)
   cCloseCursor (if using jde cache or other "cursor" type implementation
   idCursorHandle (if using jde cache but could be anything to indicate position in the recordset)
   [data]
TermFunction
	- Frees all resources.


Find Button Event Logic may be something like this:
Code:
IterFunction ;--If using cursors or other "cursor" type resources this can close any open cursor type resources (open due to pagination)
TermFunction ;--term any previous "session"  (due again to pagination)
InitFunction ;--run logic to build recordset or whatever


Grid's Get Custom Grid Row Event:
Code:
IterFunction ;--return records until there are no more
if cEndOfList != '1'
	insert grid buffer row	
	continue custom data feth (or whatever the sys func is called)
else
	TermFunction  (or leave it open until the next find button press or form close)

With this pattern you still get the built in pagination of the APPL so that if your query has a large number of records, ony n rows are returned at a time (provided you left that option on in the grid properties). Like I said, performance is great with the repeated calls to IterFunction - I have filled a grid with 1000s of records in no time at all.

Your init function can store the results in cache or simple run the query and maintain a reference to the recordset on the DB server and then iterate that recordset with calls to IterFunction. The latter would save memory on the ES server for very large result sets but would need to keep the recordset open on the DB server.
 

Oskr

Member
hhmmm...

Hello, thanks for help.
craig_welton: "There are a ton of jdeGrid* functions you can use. If anyone has a solution for the HTML presentation, that would be great to hear. There are APIs to control the appearance of the web grid, but not to add rows AFAIK."

¿why couldn´t the 'GetDlgItem' or 'jdeGridAddRow' run on web client?, I assumed that the standard code in C work in both scenarios... except WinAPI functions that run just on ES... and ¿what is the AFAIK?, excuse my ignorance. ¿where can I find the ton of jdeGrid* functions docs?... I've been on fat client with a work mate and these are not here...

BOster: I understand what you say, I'm just trying to avoid a call a C-function each time the NER code needs a new record, by experience in another platforms I've seen which this is not healthy when we're treating with so many records. But, let's suppose that performance won't be a problem anymore... I've seen JDE become unstable when there is a problem with a library, in that case some programs get stopped and their resources are not freed... when this happens again the program which is using the C-Code function could perfectly to be aborted (i guess) and the library never will receive the 'TermFunction' signal for releasing the allocated dynamic memory structures and other handles (like the NamedPipes, Sockets, etc, etc)...
Because of this, the service in the server must be alert if the client is so delayed (the C-Code) and then free his resources (the server) and the client would have then a few handles, no data structures nothing else, but this is possible only if i can get access to GC and I/O operations over him, it means, only one function... it was executed one time, it finished the work, freed any adquired resource and went out clean.

One more time, sorry for bad writing, this is not my native language.
 

BOster

Legendary Poster
Actually my method is very stable and I have used it quite extensively in one form or another.

If you architect your C BSFNs the correct way resource leaks can almost be entirely eliminated. If, for example you execute your query and temporarily store the results in jdeCache (so that you can close your recordset or free any other resources used to build the recordset), jdeCache will get cleaned up in the event the JAS server crashes or something else causes your "term" BSFN to not be called. When the JDE Enterprise Server user session times out any memory allocated through jdeCache API calls is free'd. If you use linked lists or some other form of malloc those resources are not and will remain allocated until the COK process terminates. The only real problem with temporarily storing your results in jdeCache is if your result set is exceptionally large - but then you would have the same problem if you tried to push all those results to the grid on the JAS server - actually, you may have more problems.

Having said all that, JDE has gotten pretty good at cleaning up resources when things go wrong. On the browser there is browser close detection that will try to gracefully shut down open applications if the user just clicks the "X" on a tab or the browser and then any cleanup code should execute. On the JAS server when the user's JAS server session times out it will try to gracefully close down open applications and again should call any cleanup code, and as stated when the user's Enterprise Server session times out it will free memory allocated through the jdeCache API calls (not necessarily a "graceful" cleanup but at least it reduces memory leaks). And finally their is COK recycling.

When coding BSFNs where resources are allocated in one BSFN call and then free'd in a later BSFN call I try as much as possible to do any dynamic memory allocation using jdeCache and avoid as much as possible LINKEDLIST or malloc (jdeAlloc). For dynamic memory allocations within a single BSFN call I will often use jdeAlloc and/or LINKEDLIST but I usually try to have those resources free'd before the BSFN call returns and not rely on a later BSFN call to free those resources.

Using the init/iter/term pattern I outlined "fits" the JDE APPL design model nicely. The grid event "Get Custom Grid Row" exists for that exact reason - filling a grid programatically instead of through a databound recordset (business view). It also makes your code self documenting and easy to understand for the client developer (the programmer coding the APPL that has to use your BSFN calls). It preserves a lot of the built in grid functionality like pagination and the grid event model. It also makes the grid more extensible in that it won't break if some other developer comes along after you and adds a grid column that is not connected to your "Fill Grid BSFN" - if they do want to fill that column it is very easy to follow the trail to figure out what BSFN(s) needs to be modified.

If I were you:

Init BSFN Call
- connect to external data source or system, execute query or what ever, build result set in jdeCachje
Iter BSFN Call
- iterate the jdeCache records
Term BSFN Call
- destroy jdeCache (again if the term call doesn't happen this memory will eventually be free'd when the user ES session times out)
 

craig_welton

Legendary Poster
GetDlgItem is a WIN32 API to get the window handle from a dialog resource. The grid APIs are specific to the grid control JDE uses in the fat client. None of these will work in the HTML presentation. If you want to see the fat client APIs do a Find In Files for jdeGrid from Visual Studio and look in the system\include directory of your JDE install.

Honestly, I'd listen to what BOster has provided. I do the same thing in a lot of cases and he explained it very well.

Craig

AFAIK = "as far as I know"
 

Oskr

Member
Well...

GetDlgItem is a WIN32 API to get the window handle from a dialog resource. The grid APIs are specific to the grid control JDE uses in the fat client. None of these will work in the HTML presentation. If you want to see the fat client APIs do a Find In Files for jdeGrid from Visual Studio and look in the system\include directory of your JDE install.

Honestly, I'd listen to what BOster has provided. I do the same thing in a lot of cases and he explained it very well.

Craig

AFAIK = "as far as I know"

Thanks for the responses, I was thinking GetDlgItem belongs to JDE API, because of this I was wondering why t just worked on fat client... the method described above by BOster is very similar to what I have supposed in case I couldn't change on runtime the GC, except by I don't use JDE API functions, instead of this, I build DLL libraries (with Borland/CodeGear C++ compiler or MinGW[GCC]) that facilitate the JDE programming on C for these developers. In this case I won't develop a DLL else a .C/.H file so the can access the external service from their JDE code without instancing external procedures.

I don't know much about jdeCache, also the JDE functions documentation is small (at least till where i have searched), I can see the resources managing complexity must be recharged on the service, so the client will just open an connection to a NamedPipe, the rest belongs to the NER code... as simple as possible.

Thanks everyone for attending this thread. :D
 
Top