SYSDUMPs AND HP's "TurboSTORE" FACILITY
                       by Eugene Volokh, VESOFT
              Published by INTERACT Magazine, Sep 1988.


   At a recent meeting of the GLUG (Greater Los Angeles Users' Group),
one  of our users approached me with  a technical problem. He had just
bought  HP's  new TurboSTORE product, which  (among other things) lets
you  mount  several tapes on several tape  drives and then specify all
those  tape  drives  on one :STORE command.  This way, if your nightly
backup  takes 3 reels and you happen  to have 3 tape drives, you could
mount tapes on each of the tape drives and say:

   :FILE T7;DEV=7
   :FILE T8;DEV=8
   :FILE T9;DEV=9
   :STORE @.@.@;DATE>=xxx;STORESET=(*T7),(*T8),(*T9)

Instead  of  just  specifying  the  tape  file to store  to (after the
fileset), you can specify the ;STORESET= keyword; :STORE will write to
the  tape on ldev 7, then to the one on ldev 8, and then to the one on
ldev  9.  You  mount the tapes, do the :STORE,  and then go home -- no
need  to stay around to mount additional tapes. (This works especially
well  if you have HP's new 7980XC compressing tape drives, which could
let  you cut your system backup to 2 or  3 tapes rather than 7 or 8 --
the user who prompted this whole paper is getting a 4 to 1 compression
ratio.)  It's  much  more  convenient,  and  can save you  $$$ on your
nightly operator costs.

   The problem with TurboSTORE is that, although it works perfectly on
the  :STORE  command, it can't be used  with :SYSDUMP -- the one place
you most want to have it (for backup purposes). If you try saying

   :FILE T7;DEV=7
   :FILE T8;DEV=8
   :FILE T9;DEV=9
   :SYSDUMP (*T7),(*T8),(*T9)

instead of

   :SYSDUMP *T

you'll get a syntax error; if you say

   :SYSDUMP *T
   ...
   ENTER DUMP FILE SUBSET (S)
   @.@.@;STORESET=(*T7),(*T8),(*T9)

then  you'll get an error "'STORESET' NOT ALLOWED WHEN POSITIONAL TAPE
NAME IS SPECIFIED (S/R 6293)".

   Thus,  you either have to abandon TurboSTORE for system backups (if
you  do,  why  use  TurboSTORE  at  all? -- how  many other multi-reel
:STOREs  do  you  do?) or do all your  system backups with :STORE. The
latter alternative -- using :STORE for backups -- seems palatable, but
has two substantial problems:

   1. Backups made with :STORE do not contain the SYSTEM DIRECTORY. If
      you need to restore from a :STORE backup, the best you can do is
      put  on a ;CREATE, but that still might not create all the users
      and  groups, and certainly won't preserve capabilities, security
      masks, etc.

      Your  normal coldload tape (which you had to make with :SYSDUMP)
      would  have this information, but unless  you cut a new coldload
      tape  every  night,  the  directory  information  on it  will be
      substantially out of date.

   2. While you can :RESTORE equally well from a :STORE backup as from
      a  :SYSDUMP backup, you can't do  a RELOAD COMPACT from a :STORE
      tape.  If  you  like  to  use this option  for better disc space
      utilization, switching to :STORE backups may be unpleasant.

   Well,  you  say, these might be  non-trivial problems, but what can
you  do?  If that's the way TurboSTORE works,  we have to live with it
and  wait  for a new version that might  fix the problem (which may be
some time down the road).

   Fortunately,  our  user  was an imaginative type  -- he though that
something  could be done directly, without having to wait. Even when I
assured  him that the problem was probably quite deep and intractable,
he  still  goaded  me  to go on; and, as  it ultimately turned out, we
managed to come up with a very simple solution.

   The  :SYSDUMP command does not write the files-to-be-stored to tape
itself;  it  uses  :STORE  to  do  this. After writing  all the system
information  to the backup tape,  it creates STORE.PUB.SYS (the :STORE
program)  as a son process and tells  it (via the ;INFO= string) which
files  are to be stored. Actually,  it passes to STORE.PUB.SYS all the
text  that  you typed in response to  "ENTER DUMP FILE SUBSET (S)", so
any       :STORE       keywords       specified       there      (e.g.
"@.@.@;STORESET=(*T7),(*T8),(*T9)")  are  seen  by  STORE.PUB.SYS.  In
fact, if you say

   :SYSDUMP *T
   ...
   ENTER DUMP FILE SUBSET (S)
   @.@.@;STORESET=(*T7),(*T8),(*T9)

then  SYSDUMP will essentially do  (using the CREATEPROCESS intrinsic)
the equivalent of

   :RUN STORE.PUB.SYS;&
        INFO="STORE @.@.@;*DUMPTAPE;STORESET=(*T7),(*T8),(*T9)"

The  only reason why this fails seems to be that STORE.PUB.SYS doesn't
let  you  specify  both  the  "storefile"  (*DUMPTAPE)  parameter  and
;STORESET=.  It's  purely  a  syntax  check  on STORE's  part; if only
SYSDUMP had done a

   :RUN STORE.PUB.SYS; INFO="STORE @.@.@;STORESET=(*T7),(*T8),(*T9)"

-- without specifying *DUMPTAPE -- then everything would work! SYSDUMP
would  write all the system stuff to  the store file you specified (in
our example, *T, which SYSDUMP later refers to as *DUMPTAPE), and then
use  STORE.PUB.SYS to write all the  files to the given ;STORESET=. Of
course,  *T (the SYSDUMP tape) would have  to be on the same device as
*T7 (the first tape in the ;STORESET= parameter).

   (Note   that  SYSDUMP  always  refers  to  the  tape  parameter  as
*DUMPTAPE,  even though you specified it as *T -- the :SYSDUMP command
automatically sets up a ":FILE DUMPTAPE=*T" file equation.)

   So  now  we  know  what  we  wish SYSDUMP would do  -- not pass the
*DUMPTAPE  parameter  to  STORE.PUB.SYS  when  the  user  specifies  a
;STORESET=  parameter. Now, the question is: how do we make SYSDUMP do
it?  How  do we force an HP program  (the source of which we don't, of
course, have) to do something it wasn't designed to do?

   The  solution is surprisingly simple. In  fact, it does NOT involve
patching  any  SYSDUMP  code  (which would be  highly uncertain, which
would constrain the nature of our patch, and which would require us to
re-deduce  the  patch for every new version  of SYSDUMP). What it does
involve is doing the following:

   * :HELLO MANAGER.SYS

   * :NEWGROUP VESTORE.SYS;CAP=IA,BA,PH,PM,MR,DS

   * :FCOPY FROM=SYSDUMP.PUB.SYS;TO=SYSDUMP.VESTORE.SYS;NEW

   * Compile the following SPL program:

       $CONTROL NOSOURCE, USLINIT, SEGMENT=VESTORE, SUBPROGRAM
       BEGIN
       PROCEDURE CREATEPROCESS (ERR, PIN, PROGRAM, NUMBERS, ITEMS);
       INTEGER ERR;
       INTEGER PIN;
       BYTE ARRAY PROGRAM;
       INTEGER ARRAY NUMBERS;
       INTEGER ARRAY ITEMS;
       OPTION VARIABLE;
       BEGIN
       INTRINSIC LOADPROC, UNLOADPROC;
       INTEGER VAR'MASK = Q-4;
       INTEGER STATUS = Q-1;
       BYTE POINTER INFO;
       INTEGER INFO'LEN, I, J, PLABEL, IDENT;
       BYTE ARRAY PROC'NAME(0:15);

       IF VAR'MASK.(14:1)=1 AND VAR'MASK.(15:1)=1 THEN
         BEGIN   << NUMBERS and ITEMS specified, look at them >>
         INFO'LEN:=0;
         I:=0;
         WHILE NUMBERS(I)<>0 DO
           BEGIN   << find INFO and INFO LENGTH values >>
           IF NUMBERS(I)=11 <<info>> THEN
             @INFO:=ITEMS(I)
           ELSE IF NUMBERS(I)=12 <<infolen>> THEN
             INFO'LEN:=ITEMS(I);
           I:=I+1;
           END;
         IF INFO'LEN<>0 THEN
           FOR I:=0 UNTIL INFO'LEN-11 DO
             IF INFO(I)=";STORESET=" THEN   << store-set specified? >>
               FOR J:=0 UNTIL INFO'LEN-12 DO
                 IF INFO(J)=";*DUMPTAPE;" THEN
                   MOVE INFO(J):="          ;";   << delete *DUMPTAPE >>
         END;
       << Can't call CREATEPROCESS directly (this would just call >>
       << this procedure recursively) -- LOADPROC it and then call. >>
       MOVE PROC'NAME:="CREATEPROCESS ";
       IDENT:=LOADPROC (PROC'NAME, 0, PLABEL);
       TOS:=@ERR;
       TOS:=@PIN;
       TOS:=@PROGRAM;
       TOS:=@NUMBERS;
       TOS:=@ITEMS;
       TOS:=VAR'MASK;
       TOS:=PLABEL;
       ASSEMBLE (PCAL 0);
       IF > THEN STATUS.(6:2):=0    << set condition code >>
       ELSE IF < THEN STATUS.(6:2):=1
       ELSE STATUS.(6:2):=2;
       UNLOADPROC (IDENT);
       END;
       END.

   * Add it to a group SL by saying

       :SEGMENTER
       -BUILDSL SL.VESTORE.SYS,20,1
       -USL $OLDPASS  (or whatever USL you compiled the above
                       SPL procedure into)
       -ADDSL VESTORE
       -EXIT

   * Now, whenever you want to do a system backup, instead of
     saying ":SYSDUMP *T,*LISTFILE", say

       :FILE DUMPTAPE=*T
       :FILE SYSDLIST=*LISTFILE  (or $STDLIST, if you like)
       :RUN SYSDUMP.VESTORE.SYS;LIB=G

   * When SYSDUMP.VESTORE.SYS prompts you with "ENTER DUMP FILE
     SUBSET (S)", say

       fileset,fileset,...,fileset;STORESET=(*tape,*tape,...)

     In  other  words, specify everything  that you'd normally specify
     when  asked  for  the  dump  file  subsets,  PLUS  the ;STORESET=
     parameter that you'd specify on an ordinary :STORE command.

   Now,  SYSDUMP.VESTORE.SYS  --  an exact copy  of SYSDUMP.PUB.SYS --
will do your system backup USING TurboSTORE'S ;STORESET= KEYWORD.

   How  does this work? Well,  when SYSDUMP.VESTORE.SYS (which was run
with   ;LIB=G)   calls   the   CREATEPROCESS   intrinsic   to   create
STORE.PUB.SYS,  it will actually call  our own CREATEPROCESS procedure
that we've put into SL.VESTORE.SYS.

   This  CREATEPROCESS procedure looks  exactly like the CREATEPROCESS
intrinsic; however, it also examines the ;INFO= parameter that's being
passed  to  the program-to-be-created. (We find  the ;INFO= string and
its  length in the NUMBERS and  ITEMS arrays passed to CREATEPROCESS.)
If  this  ;INFO=  string  contains  the string  ";STORESET=", then our
CREATEPROCESS  procedure  REMOVES  the  string  ";*DUMPTAPE"  from the
;INFO= parameter.

   After   this   is  done,  our  own  CREATEPROCESS  calls  the  REAL
CREATEPROCESS. Unfortunately, it can't just simply call CREATEPROCESS,
since  that  would call our own  CREATEPROCESS recursively (instead of
calling  the  real  CREATEPROCESS  in the system  SL). Instead, we use
LOADPROC  to load the real CREATEPROCESS explicitly from the system SL
and then call it using PCAL 0.

   :SYSDUMP  and  TurboSTORE  can now work  together. The customer for
whom  we originally did this is  using this quite successfully for his
nightly  backups. There may be some problems with our approach that we
haven't  encountered  (use  it at your own risk!),  but it seems to be
working  quite  well.  If  you're a TurboSTORE customer,  try it -- it
might help you out of an unpleasant spot!

Go to Adager's index of technical papers