Announcement

Collapse
No announcement yet.

How does the service program work?

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

  • How does the service program work?

    Hello. I am experimenting with creating a service program. To do this, I created a service program with one function, as well as a regular program that uses a function from the service program.

    Explain why it is possible to delete the service program after starting the program and while it is running? Where does the program get the function code that it took from the service program?
    Also, if during the execution of the program, replace the service (and change the function algorithm in it), then the running program will not notice this. It will continue to perform the "old" function.

    What kind of magic?

  • #2
    This is just situation normal. An instance of the Service Program (SP) is activated in the Activation Group (AG) depending on how the SP was compiled. Normally in the same AG as your program (i.e. SP compiled *CALLER). That activation is going to remain available as long as the containing AG remains. RCLACTGRP AGname or End job and the AG goes away and with it the SP.

    This is really the same behaviour as a program. You can recreate a program while it is active in a user job and the old copy continues to be used until all active instances of it have been deactivated.

    Comment


    • #3
      Thanks JonBoy!
      It turns out that when SP is activated, not only data, but also a code are included in the activation group? What happens if a small program calls one small function from SP, created with ACTGRP = * CALLER, when the SP itself has thousands of functions and is several gigabytes in size? Will the entire SP be "copied" to the small program activation group? Or just a part of the SP (small function)?

      Comment


      • #4
        The following is a simplification but is "good enough".

        Nothing is copied - so much of your question is not answerable. In essence what happens is that when an SP is activated the calling program receives a pointer to the activation. An allocation in memory (associated with the AG) is made for the variable storage needed by the SP. This happens whether one procedure or a thousand are used. BUT no copy of the SP logic code is made. The pointer to the SP is in the AG and so will persist as long as the AG persists.

        So - now we recreate the SP. That becomes a new object in the system with a unique address. Any new program running in a _different_ AG will receive a pointer to this new object. But the old one still exists because in a single-level store system all addresses are unique and therefore the old SP is still "hanging around".

        From a design perspective the number of procedures in an SP should be a consideration because of the activation overhead. For example designing to have a single SP containing every single procedure used by every single application would probably be OK in an interactive system and nobody would really notice the time it took to load up if you made sure it happened during the normal sign on process. BUT it would be a lousy design if a lot of batch work also took place and perhaps each batch job only used two or three procedures before the job ended. SP design requires balancing these different needs. But I would say that 1,000 procedures in an SP is nearly always a bad idea.

        Comment


        • #5
          JonBoy you are as always on top!
          Explain one more point. You write that the old object (the program I deleted) still exists. And when is it physically removed from the disk? When will there be no activation group left that refers to it?

          Comment


          • #6
            Thanks for the compliment!

            As to your question - the "secret sauce" is the QREPLOBJ library. This is where the systems "moves" things when they are replaced while in use. See https://www.ibm.com/support/pages/qrplobj-library

            It is cleaned out by an IPL and if it gets too big you can tidy it up yourself - but I honestly cannot remember the last time I ever had to do that. This document does a good job of explaining clean up. https://www.ibm.com/support/pages/cl...bj-without-ipl

            Just google QREPLOBJ form more if you are curious.

            Comment


            • #7
              Slight typo there - the library is QRPLOBJ.

              Cheers,

              Emmanuel

              Comment


              • #8
                Originally posted by d7d1cd_ View Post
                Explain why it is possible to delete the service program after starting the program and while it is running? Where does the program get the function code that it took from the service program?
                Hmm... I don't think this is true? In my experience it fails with MCH3402. But, I don't have time right now to try to reproduce that.

                Originally posted by d7d1cd_ View Post
                Also, if during the execution of the program, replace the service (and change the function algorithm in it), then the running program will not notice this. It will continue to perform the "old" function.
                This is the QRPLOBJ stuff that the others are talking about. If you create a program or service program with REPLACE(*YES) the original one goes to the QRPLOBJ library but keeps the same address so anything currently referring to it will still work.

                But, I've never heard of that happening with a DLTPGM or DLTSRVPGM? Replacing is not the same as deleting.

                Comment


                • #9
                  Originally posted by Scott Klement View Post
                  But, I've never heard of that happening with a DLTPGM or DLTSRVPGM? Replacing is not the same as deleting.
                  Scott, nevertheless it is.

                  I have now run the experiment again. First created the SP:
                  Code:
                  int srvFoo1 (int i) {return i; }
                  int srvFoo2 (int i) {return i - 1; }
                  int srvFoo3 (int i) {return i + 1; }
                  Then I created the program:
                  Code:
                  #include <cstdio>
                  #include <unistd.h>
                  
                  int srvFoo1(int);
                  int srvFoo2(int);
                  int srvFoo3(int);
                  
                  int main () {
                  for (int i = 1; i <= 10; ++i) {
                  std::printf ("srvFoo1 (%d) = %d\n", i, srvFoo1 (i));
                  sleep (1);
                  }
                  
                  for (int i = 1; i <= 10; ++i) {
                  std::printf ("srvFoo2 (%d) = %d\n", i, srvFoo2 (i));
                  sleep (1);
                  }
                  
                  for (int i = 1; i <= 10; ++ i) {
                  std::printf ("srvFoo3 (%d) = %d\n", i, srvFoo3 (i));
                  sleep (1);
                  }
                  }
                  Then I cleaned and launched the program. During its execution, I removed SP (DLTSRVPGM), but this did not affect the already working program in any way: it worked to the end.

                  Comment


                  • #10
                    I also wanted to add that SP was created with the EXPORT (* ALL) option.
                    The observed behavior is probably correct. Otherwise, how to replace SP on a running system (when SP is used by many programs and which are running at the current time)?

                    Comment

                    Working...
                    X