ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Handler on RPG WORKSTN file

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Handler on RPG WORKSTN file

    I have succeeded in getting the HANDLER keyword to work on a WORKSTN file (i.e. a Display File) defined in an RPG IV program. As expected, my handler program is called on every RPG file operation (OPEN, EXFMT, CLOSE, etc.) and can pass data to/from the program using the provided output and input buffers.

    However, the program now ONLY works with the handler and no longer as a typical interactive program which presents a user interface on the (5250?) terminal screen.

    I wondered if there is any option such as (e.g.) HANDLER(*NONE) and/or a way to 'deactivate' the handler without re-compiling/re-creating the program. I thought the OVRDSPF command might provide a way to do this, but it doesn't as far as I can see.

    Is there any way to do this?

    (Thanks in advance)

  • #2
    No, there's no way to have a single program that sometimes using a handler and sometimes uses the system's file handling.

    I think the easiest way to handle (heh) this situation is to condition the HANDLER keyword with /IF so you can compile the program two ways. You could have a wrapper program that decides which version of the program to call.

    Comment


    • #3
      It is possible, but you have to do the leg work yourself. Our handler program has a switch in it than can work out whether it's running in our screen-scraping mode, or in traditional 5250 telnet.

      For the latter case, we just act as a proxy for the <recio.h> APIs, passing the data between them and the Open Access buffers. They're targeted for C programmers but thanks to the magic of ILE you can use them just fine in RPG too.

      Comment


      • #4
        We do the same thing that Martin mentioned. If 5250 is desired, the handler sends the display file records to the ILE C recio routines so that it works in green-screen. If not, we take control and (in our case) do web.

        Comment


        • #5
          Could file conditioning indicators help? EXTIND(*INU1) on the file description spec

          Comment


          • #6
            More modern than EXTIND(*INU1) would be to use a named indicator (maybe as a parameter) with USROPN and the OPEN/CLOSE opcodes. But, whether you use EXTIND or USROPN, either way you'd need two separate F-specs, two sets of record formats, and every opcode that references them would have to be conditioned to use one or the other record format. So, this would mean making some signfiicant changes to every program.

            Whereas, with Barbara's /IF DEFINED method, you only have to compile the program twice and keep two objects. Only very small changes needed to the source.

            With Martin (and my) suggestion, the changes are only in the handler, so no need to change all the callers at all. (But the changes require a deeper understanding of what you're doing -- but this shouldn't be a big deal if you're writing OA handlers.)

            Comment


            • #7
              Barbara/Martin/Scott/UserName10,

              thanks for all the replies! I've added the /IF, /ELSE, /ENDIF compiler directives around 2 versions of the 'dcl-f' specification for now and that means I can easily re-create both versions of the program using the DEFINE parameter on the CRTRPGMOD command. But I like this idea of using the <recio.h> functions to read from/write to the display file so I'll try to make that work on Monday.


              Comment


              • #8
                I've basically made the <recio.h> functions work with my Display File - I've only ever used <recio.h> with Database files before so I've had to use a few new (to me) functions such as _Rformat() to set the record format name before reads/writes and (I've assumed) _Rwriterd() to handle the 'EXFMT' operation. The 'OPEN', 'CLOSE', 'READ' and 'WRITE' operations in RPG seem to naturally correspond to functions _Ropen(), _Rclose(), _Rreadn() and _Rwrite() so I've used those. I've used the following page as a reference for these (yes, we're still on V7R1): https://www.ibm.com/support/knowledg...sc41560717.htm

                Some more work will be needed to implement subfile operations such as 'READC' and 'CHAIN', but I'm assuming it'll be similar.

                Some questions which arose during this development:

                1) when handling the 'OPEN' operation on the Display File, my code calls the _Ropen() function which returns a file pointer. This pointer value obviously needs to be stored so it can be used on subsequent READ/WRITE/CLOSE/etc. operations, but where is the best place to store it? As the structure passed to the handler doesn't seem to include any kind of 'instance' or 'handle' which could be used to store and retrieve this (and other) value(s) in some kind of memory structure, I decided to put it in the optional 2nd variable that's specified on the HANDLER keyword (received as a pointer to a 'user area' in the handler program), but I'd rather avoid that since it adds a bit more complexity to the interactive program on which I'm trying to make the impact minimal. I thought about adding some code to maybe get a reference or pointer to the Call Stack Entry of the interactive program and use that as some kind of 'lookup instance' for a memory structure, but that seems unnecessarily complex (?). Is there a better way to do this?

                2) when using _Rwriterd() to handle the 'EXFMT' operation, the function receives a file pointer, a buffer (pointer) and a buffer size (size_t, which I've defined as UNS(10) but wonder if it should be UNS(5)??) so I'm assuming that the same buffer must be used for both 'input buffer' and 'output buffer'. However, these buffers often appear to be of different sizes for Display File record formats (I think this is probably because some fields are 'input only', some 'output only' and some 'both'). I've therefore determined the larger of the 2 buffer sizes and passed this value in the 3rd parameter to function _Rwriterd(). This seems to work, but is it correct or do I have some potential memory overwriting problem here? Would it possibly be preferably to use _Rwrite() followed by _Rreadn() rather than _Rwriterd() to handle the 'EXFMT' operation?

                Thanks in advance for any insights.


                Comment


                • #9
                  1) The Open Access buffer gives you a subfield called StateInfo for each ODP. You can dynamically allocate some memory to hold your file pointer, and then store the pointer to that structure here.

                  There's a bit of an example here, under the "Main Handler Procedure" section: https://www.ibm.com/support/knowledg...accexample.htm

                  2) I have size_t defined as an uns(10). As for using _Rwriterd(), I'm not too sure how that's supposed to work. We actually use _Rwrread(), which allows separate input and output buffers to be passed.

                  Comment


                  • #10
                    Thanks Martin!

                    I've done exactly what you suggested - using the StateInfo to store the file pointer and using function_Rwrread() with its separate buffers. Seems to work well...

                    Comment


                    • #11
                      My EXFMT routine calls _Rwrited(), followed by _Rreadn(). I also update the open feedback info by calling _Riofbk() after reading.

                      Comment


                      • #12
                        Thanks Scott!,

                        are there particular reasons to use _Rwrited() as opposed to _Rwrite() and/or _Rwrread() - either for Display Files specifically or in general?

                        Comment


                        • #13
                          I don't know, sorry.

                          The reason I use _Rwrited() is because I have a Write() routine that is called for the write opcode, and a Read() routine that is called for the read opcode. Rather than write a 3rd routine for EXFMT, I call my existing Write() followed by Read()

                          Comment


                          • #14
                            Hi,
                            i've successfully written my own handler for workstation display file, but now i need that the handler sometimes sends data to the web (my handler) and sometimes "does" the normal work (5250).
                            I've found this thread and it's really interesting. Just for ask, can you share the part of your handler code for 5250? I would be very grateful.
                            Thank you.

                            Comment

                            Working...
                            X