;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Copyright 2005, 2010 Fidelity Information Services, Inc ; ; ; ; This source code contains the intellectual property ; ; of its copyright holder(s), and is made available ; ; under a license. If you do not know the terms of ; ; the license, please stop and do not read further. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; If invoked as "mumps -run v5cbsu", this is the V5 Certify Block Split Utility ; Reads scan phase output file from DBCERTIFY and processes level-0 GVT blocks. ; Rewrites the scan phase output file minus those blocks. ; ; If invoked as "mumps -run dump^v5cbsu", this is the DBCERTSCAN file dump utility. ; Reads scan phase output file from DBCERTIFY and prints the contents of the ; records that it finds. Does not touch the database or the scan file. ; Only dumps the contents. ; On OpenVMS, "define gtm_v5cbsu dump" to invoke the dump utility. ; ; On OpenVMS, "define gtm_v5cbsu fix512" to remove zero padding ; which may have been added during dbcertify scan runs on some ; OpenVMS 7.3-1 systems. This produces an output file with a ; suffix of _FIX512 to be used as input to v5cbsu (after ; deassigning gtm_v5cbsu) or dbcertify certify. Both "dump" and ; "fix512" can be specified in the value of gtm_v5cbsu for the same run. ; ; Note that our input and output files contain binary data in the file and ; record headers. GT.M I/O does not deal with this type of data well so these binary ; stream files are treated as fixed record length files so far as GT.M is concerned ; and we do our own buffering of the read and write IOs. This is basically the same ; approach that GDE uses. ; ; If additional M utility routines are used by V5CBSU.m, remember ; to modify the gtmdckitinstal.com section which creates GTMDCBUILD.COM ; and any OpenVMS test system scripts which link V5CBSU. ; v5cbsu If ($data(dumpmode)=0) set dumpmode=0 Set p1outfile=$ZCMDLINE If p1outfile="" Use $P Write "Must specify the name of the SCAN phase output file",! Halt D init Do doopen(.p1outfile,readflg) D readp1hd If p1tag'=p1tagread Do Quit . Use $P . Write "%GTM-E-DBCBADFILE, Source file ",p1outfile . Write " does not appear to have been generated by DBCERTIFY SCAN - rerun SCAN or specify correct file",! set quitnow=0 If 'dumpmode&'fix512mode Do If quitnow Quit . If (0=gvtleafc) Use $P Write "There are no GVT leaf (level 0) blocks to process in this database",! Set quitnow=1 Quit . If (version="V4.4-004")!(version]"V4.4-004") View "GVDUPSETNOOP":0 . Set dbfname=$View("GVFILE",regnameP) . If dbfnP'=dbfname Do Quit . . Use $P . . Write "Database for region ",regnameP,"(",dbfname,") does not match the recorded name from the scan phase (",dbfnP,")",! . . Set quitnow=1 . ; . ; Process the input file. Any records we do not handle are rewritten to tmpfile1. . ; . Do doopen(.tmpfile1,writeflg) . Set outrecs=0,byprecs=0,prorecs=0,releaf=0 If fix512mode Do . Set tmpfile1=p1outfile_"_FIX512" ; File without zero padding . Use $P Write "V5CBSU: FIX512 mode, use "_tmpfile1_" for real v5cbsu or dbcertify certify input",! . Do doopen(.tmpfile1,writeflg) . Do dowrite(.tmpfile1,p1hdr) ; copy header as is If dumpmode Do . Use $P . Write !!,"Database referenced: ",dbfnP,! . ; . ; Process the input file. . ; . Write " BlkNum BlkType BlkLevl BlkKey",!! For rec=1:1:blkcnt Do . If $TLevel Use $P Zshow "*" Write "V5CBSU - GTMASSERT: $TLEVEL non zero at top of processing loop",! Halt . Do readp1rc(.p1outfile) . If dumpmode Do . . Use $P . . Write $$FUNC^%DH(blknum,8)," ",blktypes(blktype)," ",$J(blklevl,6)," " . . If akeylen'=0 Write reckey . . Write ! . If fix512mode Do . . Set p1rec=p1rec_reckey . . Do dowrite(.tmpfile1,p1rec) ; copy record header and key . If 'dumpmode&'fix512mode Do . . TStart ():TRANSACTION="BATCH" ; BATCH needed to avoid hardening wait in case of journaling . . Set processed=0 . . If ""'=reckey Do . . . Set exist=$DATA(@reckey) . . . If (1=exist)!(11=exist) Set value=$Get(@reckey) Set @reckey=value Set processed=1 . . TCommit . . If processed=1 Set prorecs=prorecs+1 . . Else Do . . . If ""'=reckey Set byprecs=byprecs+1 Set p1rec=p1rec_reckey . . . Do dowrite(.tmpfile1,p1rec) . . . Set outrecs=outrecs+1 . . . If gvtleaf=blktype Set releaf=releaf+1 ; This is a leaf block we did not process ; ; If in dump mode, close input file and we are done. ; If in fix512 mode, close input and output file and we are done. ; If in regular mode, close input and output file. Also open new output file ; that will include the fileheader with the correct record count ; Do doclose(.p1outfile) If dumpmode&'fix512mode quit Do doclose(.tmpfile1) If fix512mode Quit Set newp1hdr=p1tag_$$num2bin(hdrtn)_$$num2bin(outrecs)_$$num2bin(totblks)_$$num2bin(dtleafc)_$$num2bin(dtindxc) Set newp1hdr=newp1hdr_$$num2bin(releaf)_$$num2bin(gvtindxc)_regname_$Char(0)_dbfn_$Char(0)_$$num2bin(uidlen)_uniqueid Set $Piece(hdrpad,$C(0),33-$Length(uniqueid)+filBufSz-360)="" ; create zero padding of correct length to fill fixed size hdr Set newp1hdr=newp1hdr_hdrpad If $Length(newp1hdr)'=p1hdrlen Do . Use $P . Zshow "*" . Write "V5CBSU - GTMASSERT: New fileheader not expected size. Size is ",$Length(newp1hdr)," - Expecting ",p1hdrlen,! . Halt Do doopen(.tmpfile1,readflg) Do doopen(.tmpfile2,writeflg) Do dowrite(.tmpfile2,newp1hdr) For recs=1:1:outrecs Do . Do readp1rc(.tmpfile1) . If ""'=reckey Set p1rec=p1rec_reckey . Do dowrite(.tmpfile2,p1rec) ; ; New version of dbcertp1 file is written to tmpfile2. Close both files and effect the proper name change. ; Do doclose(.tmpfile1) Do doclose(.tmpfile2) If VMS Set rename="RENAME" Set renamever=";" Set delete="DELETE" Set delver=".*" Else Set rename="mv" Set renamever="" Set delete="rm -f" Set delver="" If 'VMS ZSystem delete_" "_p1outfile_"_orig" ; in VMS multiple versions would be automatically created ZSystem rename_" "_p1outfile_renamever_" "_p1outfile_"_orig"_renamever ZSystem rename_" "_tmpfile2_renamever_" "_p1outfile_renamever ZSystem delete_" "_tmpfile1_delver Use $P Write "Scan phase records read: ",blkcnt,! Write "Scan phase records bypassed: ",byprecs,! Write "Scan phase records processed: ",prorecs,! Write "Scan phase records left: ",outrecs,! Quit ; ; Entry point for DUMP mode operation (dump contents of scan file) ; dump ; set dumpmode=1 Do v5cbsu quit ; ; Read in scan phase file header ; readp1hd Set p1hdr=$$doread(.p1outfile,p1hdrlen) Set p1tagread=$Extract(p1hdr,1,8) Set hdrtn=$$bin2num($Extract(p1hdr,9,12)) Set blkcnt=$$bin2num($Extract(p1hdr,13,16)) Set totblks=$$bin2num($Extract(p1hdr,17,20)) Set dtleafc=$$bin2num($Extract(p1hdr,21,24)) Set dtindxc=$$bin2num($Extract(p1hdr,25,28)) Set gvtleafc=$$bin2num($Extract(p1hdr,29,32)) Set gvtindxc=$$bin2num($Extract(p1hdr,33,36)) Set regname=$Extract(p1hdr,37,67) ; 1 byte of filler we don't care about Set dbfn=$Extract(p1hdr,69,323) ; 1 byte of filler we don't care about Set uidlen=$$bin2num($Extract(p1hdr,325,328)) ; Size of field varys (by platform) length unique id fields (we don't process them) Set uniqueid=$Extract(p1hdr,329,329+uidlen-1) ; Eliminate trailing nulls Set regnameP=$Piece(regname,$Char(0),1) Set dbfnP=$Piece(dbfn,$Char(0),1) ; Now that we have a region name, define our temps with regname embedded Set tmpfile1="dbcertp1"_regnameP_".tmp1" Set tmpfile2="dbcertp1"_regnameP_".tmp2" Quit ; ; Read in scan phase record (fixed size with optional varying length ascii key following) ; readp1rc(outfile) Set p1rec=$$doread(.outfile,p1reclen) Set tn=$$bin2num($Extract(p1rec,1,4)) Set blknum=$$bin2num($Extract(p1rec,5,8)) Set blktype=$$bin2num($Extract(p1rec,9,12)) Set blklevl=$$bin2num($Extract(p1rec,13,16)) Set akeylen=$$bin2num($Extract(p1rec,17,20)) If fix512mode Do . Set padnum=filBufSz-p1reclen . Set nulls=$$doread(.outfile,padnum) . If $Length(nulls,$Char(0))'=(padnum+1) Do . . Use $P ZShow "*" . . Write "V5CSBU - GTMASSERT: FIX512: No padding when expected after record header",! . . Halt If (blktype=gvtleaf)&(0'=akeylen) Do . Set reckey=$$doread(.outfile,akeylen) . If fix512mode Do . . Set padnum=filBufSz-akeylen . . Set nulls=$$doread(.outfile,padnum) . . If $Length(nulls,$Char(0))'=(padnum+1) Do . . . Use $P ZShow "*" . . . Write "V5CSBU - GTMASSERT: FIX512: No padding when expected after key",! . . . Halt Else Do . Set reckey="" . If (0'=akeylen) do . . Use $P ZShow "*" . . Write "V5CBSU - GTMASSERT: Error with non-zero akeylen for non-gvtleaf record",! . . Halt Quit ; ; Open given file (1st arg MUST be passed by refence) in read or write mode according to flag. Record flag ; in file(1) so close knows whether to flush buffer or not. Buffer for this file is kept in file(2) ; doopen(file,readflag) Set file(1)=readflag new chsetstr set chsetstr=$SELECT($ZV["OS390":":chset=""BINARY""",1:"") If readflag Open file:@("(Readonly:Fixed"_chsetstr_":RecordSize="_filBufSz_":Blocksize="_filBufSz_")") Else Open file:@("(New:Fixed"_chsetstr_":RecordSize="_filBufSz_":Blocksize="_filBufSz_")") Set file(2)="" ; Buffer for this file Quit ; ; Read given length from given file. Buffer is kept in file(2). We are rebuffering filBufSz byte fixed records ; at the real IO level for the reasons described in the module header. ; doread(file,len) New rec,br ; A record with ZWR format key can be very long indeed so read more than enough blocks to cover that ; possibility. The max is higher than needs to be but satisfies criteria of not leaving the loop unbounded. For br=1:1:mxzwrxpr Quit:$Length(file(2))'