$! $! GLOBAL_BUFFER_USAGE.COM $! $! Measure usage of the global buffers allocated to RMS files. $! $! Measure all processes present on a node. (Must be run on each node to $! gather a cluster-wide picture.) $! $! Creates a .CSV file with global buffer usage with lines in this format: $! "Filespec", Current, Peak, Total $! Filename of the .CSV file is GLOBAL_BUFFER_USAGE_date_nodename.CSV $! $! Based on GBU_ALL_CSV.COM Keith Parris, Jan.-Feb., 2008 $! KeithParris@yahoo.com or Keith.Parris@hp.com $! Version 1.3, 19-Feb-2008 $! $ if_debug = "!" !"" for debugging mode; "!" for normal mode $! The following test should probably be version-based, not architecture, as $! older Alpha versions probably have the same SDA> SHOW LOCK output format $! as the VAX Version 7.3 I used as a sample when developing this procedure. $ this_is_VAX = f$getsyi("ARCH_NAME") .eqs. "VAX" !Is this on a VAX? $! $! Check for privileges. $! $! We need CMKRNL for SDA, and some sort of file access (READALL or SYSPRV) $! to obtain file specification information for files with global buffers. $! $ auth_privs = "," + f$getjpi("","AUTHPRIV") + "," !Authorized $ cur_privs = "," + f$getjpi("","CURPRIV") + "," !Current $! Check for READALL (or SYSPRV) privilege and turn READALL on if need be $ READALL_TURNED_ON = "F" !Assume process already had READALL or SYSPRV privilege turned on $ if f$locate(",READALL,",cur_privs) .eq. f$length(cur_privs) .and. - f$locate(",SYSPRV,",cur_privs) .eq. f$length(cur_privs) $ then !READALL (or SYSPRV) privilege is not presently turned on $ if f$locate(",READALL,",auth_privs) .ne. f$length(auth_privs) .or. - f$locate(",SETPRV,",auth_privs) .ne. f$length(auth_privs) $ then $ set process/privilege=(READALL) $ READALL_TURNED_ON = "T" $ write sys$output "READALL privilege temporarily turned on." $ else $ write sys$output - "This procedure requires READALL privilege to look up file specifications." $ exit $ endif $ endif $ CMKRNL_TURNED_ON = "F" !Assume process already had CMKRNL privilege turned on $! Check for CMKRNL privilege rights $ if f$locate(",CMKRNL,",cur_privs) .eq. f$length(cur_privs) $ then !CMKRNL privilege is not presently turned on $ if f$locate(",CMKRNL,",auth_privs) .ne. f$length(auth_privs) .or. - f$locate(",SETPRV,",auth_privs) .ne. f$length(auth_privs) $ then !CMKRNL is authorized $ set process/privilege=(CMKRNL) $ CMKRNL_TURNED_ON = "T" $ write sys$output "CMKRNL privilege temporarily turned on." $ else $ write sys$output - "This procedure requires CMKRNL privilege for SDA to see global buffer usage." $ goto cleanup $ endif $ endif $! $ proc = f$environment("procedure") $ proc_dir = f$parse(proc,,,"DEVICE") + f$parse(proc,,,"DIRECTORY") $ pid = f$getjpi("","PID") $ temp_file := global_buffer_usage_csv_temp_'pid'.temp_file $ on error then goto error_exit $! $ nodename = f$getsyi("nodename") $ tim = f$time() $! date = f$cvtime(tim,"COMPARISON","DATE") !!!- "-" - "-" $ date = f$cvtime(tim,"ABSOLUTE","DATE") !!!- "-" - "-" $!! time = f$extract(0,5,f$cvtime(tim,,"TIME")) - ":" $ close/nolog tmp $ open/write tmp 'temp_file'_tmp $! $! Create SDA commands to dump RMS global buffer information for each $! process on the system. $! $ close/nolog com $ open/write com 'temp_file'_com $ write com "$ ANALYZE/SYSTEM" $! $ context = "" !F$PID context: start over $ lis1_loop: $ pid = f$pid(context) $ if pid .eqs. "" then goto lis1_eof $ usernm = f$getjpi(pid,"USERNAME") !Username $! $! List the global buffer usage for each individual process $! $! We have the PID of a process. It might possibly have files with global $! buffers open. Look at the RMS process data structures and see if there are $! any global buffers there and dump the global buffer header info to see how $! many of the global buffers are actually in use for each file. $!!! write sys$output "Looking at the following process (PID ",pid,"):" !!! $ write com "SET PROCESS/ID=",pid $ write com "SHOW PROCESS/RMS=(GBH,GBDSUM) $ goto lis1_loop $ lis1_eof: $ write com "EXIT" $ write com "$ EXIT" $ close com $! To keep from distracting the user with extraneous error messages, $! divert the numerous error messages of the following form to a file: $! %SDA-W-NOIMGRMS, no image RMS structures $! This error message occurs for each and every process on a system which $! does not happen to have a channel open to an RMS file with a global buffer. $ define/user sys$error 'temp_file'_err $! Find Global Buffer usage information for any processes using RMS global $! buffers $ @'temp_file'_com/out='temp_file'_lis $!!! type/page 'temp_file'_lis !!! $ delete 'temp_file'_com;* $ close/nolog lis $ open/read lis 'temp_file'_lis $! $! Here's a sample of what we're parsing: $! $!SDA> show proc/rms=(gbh,gbdsum) $! $!Process index: 0038 Name: FSS001 Extended PID: 312E7838 $!-------------------------------------------------------------------- $!GBH Address: 1425A000 $!- GBD_BLNK: 0000A000 $!BID: 33 51. BLN: 1A 26. $!GS_SIZE: 00028000 $!LOCK_ID: 1603F0DD $!USECNT: 00000009 SAVED_GBBD_START: 0000A000 GBD_END: 0000D180 $!GBD_NEXT: 0000A000 SCAN_NUM: 00000008 $!GBD_SYSVA: FFFFFFFD66D8A000 GBDBUFOBJ_HNDL: 00000978830E9900 $!HIT: 000367BC MISS: 00000034 $!OUTBUFQUO: 00000000 $!HASH MASK: FFFFFFC0 HASH SHIFT: FFFFFFFF $!GBIT BASE: 00000480 GBIT FREEPTR: 000005C0 $!FREELIST FLINK: 000004E8 $! BLINK: 000004E8 $!COUNT OF GBIS ON FREE LIST: 00000001 $! $! $! Press RETURN for more. $!SDA> $! $!Process index: 0038 Name: FSS001 Extended PID: 312E7838 $!-------------------------------------------------------------------- $! GBD Summary $! ----------- $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID MODE $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! $! 14266780 0000 0400 0400 0000002B 00000001 00021C00 0 71034790 1 CR $! 14266280 0000 0400 0400 00000057 00000000 0001F400 0 6F05320A 1 CR $! 14266A80 0000 0400 0400 0000002D 00000000 00023400 0 4A05DB79 1 CR $! 14267080 0000 0400 0400 00000003 00000003 00026400 0 1104B40A 1 CR $! 14265980 0000 0400 0400 00000059 00000000 0001AC00 0 1008F89F 1 CR $! 14265C80 0000 0400 0400 0000002F 00000000 0001C400 0 2C08AB18 1 CR $!... $! 14266D80 0000 0400 0400 00000029 00000000 00024C00 0 4B04A2B8 1 CR $! 14266E00 0000 0400 0400 00000055 00000000 00025000 0 170CA67C 1 CR $! 14265780 0000 0400 0000 FFFFFFFF 00000000 00019C00 0 00000000 0 $! 14265700 0000 0400 0000 FFFFFFFF 00000000 00019800 0 00000000 0 $! 14265680 0000 0400 0000 FFFFFFFF 00000000 00019400 0 00000000 0 $! 14265600 0000 0400 0000 FFFFFFFF 00000000 00019000 0 00000000 0 $! 100. GBDs were processed $!... (and so on for more Global Buffer Headers) $! $! At least some earlier versions of OpenVMS seem $! to lack the Lock Mode info, but it appears the Cache_Val field being $! non-zero may have the same meaing, so we'll use that until further $! enlightenment occurs. Here's a sample from VAX 7.3: $! GBD Summary $! ----------- $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID FLAGS $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! $! 00049950 0 1024 1024 7 00000000 00006C00 2 73000DC5 $! 00049920 0 1024 1024 4 00000000 00006800 0 01002F89 $! 000498F0 0 1024 0 -1 00000000 00006400 0 00000000 $! 000498C0 0 1024 0 -1 00000000 00006000 0 00000000 $!... $! And here's a sample from OpenVMS on Integrity 8.3-1H1. It appears the $! RMS Global Buffers are in 64-bit address space, so all the addresses are $! 64 bits instead of 32: $!Process index: 006A Name: _TNA4: Extended PID: 2CE0046A $!-------------------------------------------------------------------- $!GBH Address: 000007FDBFF52000 $!----------- $! $!GBD_FLNK: 0000000000012380 GBD_BLNK: 0000000000012000 $!BID: 33 51. BLN: 2C 44. $!GS_SIZE: 0000000000018000 $!LOCK_ID: 39003686 $!USECNT: 00000001 SAVED_GBD: 0000000000000000 $!GBD_START: 0000000000012000 GBD_END: 0000000000012480 $!GBD_NEXT: 0000000000012000 SCAN_NUM: 00000008 $!GBD_SYSVA: FFFFFFFF7807C000 GBDBUFOBJ_HNDL: 000000108A45CF40 $!HIT: 0000000000000016 MISS: 0000000000000002 $!OUTBUFQUO: 00000000 $!HASH MASK: FFFFFFF8 HASH SHIFT: FFFFFFFF $!GBIT BASE: 00000000000001C0 GBIT FREEPTR: 0000000000000200 $!FREELIST FLINK: 0000000000000000 $! BLINK: 0000000000000000 $!COUNT OF GBIS ON FREE LIST: 00000000 $! $! $! Press RETURN for more. $!SDA> $! $!Process index: 006A Name: _TNA4: Extended PID: 2CE0046A $!-------------------------------------------------------------------- $! GBD Summary $! ----------- $! GBD USE BUFFER CACHE_ $! RELADDR CNT SIZE NUMB VBN VBNSEQNUM RELADDR VAL LOCK_ID MODE $!----------------- ---- ---- ---- --- -------- ---------------- --- -------- ---- $! $! 0000000000012480 0000 0400 0400 00000007 00000000 0000000000016400 3 6B0016EF 1 CR $! 0000000000012400 0000 0400 0400 00000004 0000006C 0000000000016000 0 2A0016EE 0 $! 0000000000012380 0000 0400 0000 FFFFFFFF 00000000 0000000000015C00 0 00000000 0 $! 0000000000012300 0000 0400 0000 FFFFFFFF 00000000 0000000000015800 0 00000000 0 $! 0000000000012280 0000 0400 0000 FFFFFFFF 00000000 0000000000015400 0 00000000 0 $! $! Grab the Lock ID corresponding to the file from the Global Buffer Header $ gbh_loop: $ read/end=cleanup lis rec $!!! write sys$output "Looking for LOCK_ID:" !!! $!!! show symbol rec !!! $ if f$extract(0,8,rec) .nes. "LOCK_ID:" then goto gbh_loop $ lock_id = f$element(1," ",f$edit(rec,"COMPRESS")) $!!! show symbol lock_id !!! $ close/nolog com3 $ open/write com3 'temp_file'_com3 $ write com3 "$ ANALYZE/SYSTEM" $ write com3 "SHOW LOCK ",lock_id $ write com3 "EXIT" $ write com3 "$ EXIT" $ close com3 $!!! type/page 'temp_file'_com3 !!! $ @'temp_file'_com3/out='temp_file'_lis3 $!!! type/page 'temp_file'_lis3 !!! $ delete 'temp_file'_com3;* $ close/nolog lis3 $ open/read lis3 'temp_file'_lis3 $! Here's an example of what we're parsing: $! $!Lock Database $!------------- $! $!Lock id: 0500015C PID: 0001000A Flags: VALBLK CONVERT SYNCSTS $!Par. id: 00000000 SUBLCKs: 2 SYSTEM NODLCKW NODLCKB FFFFFFFD.68929380 BLKAST: 9F21D800 QUECVT $!Priority: 0000 $! $!Granted at EX 00000000-FFFFFFFF $! $!RSB: FFFFFFFD.6899B180 $!Resource: 004BB0E2 24534D52 RMS$â°K. Status: VALBLKR VALBLKW $! Length 26 4148504C 41020000 ...ALPHA $! Exec. mode 00202020 20535953 SYS . $! System 00000000 00000000 ........ $!01234567890123456789012345678901234567890123456789012345678901234567890 $! 1 2 3 4 5 6 7 $! $!Local copy $!--- $! or, for VAX 7.3: $! $!Lock database $!------------- $! $!Lock id: 03000374 PID: 00010012 Flags: VALBLK CONVERT SYNCSTS $!Par. id: 00000000 SUBLCKs: 16 SYSTEM NODLCKW NODLCKB $!LKB: 83641980 BLKAST: 81E1E4C6 $!PRIORTY: 0000 $! $!Granted at NL 00000000-FFFFFFFF $! $!Resource: 000300F9 24534D52 RMS$ù... Status: RESEND $! Length 26 20325359 53020000 ...SYS2 $! Exec. mode 00202020 20202020 . $! System 00000000 00000000 ........ $!01234567890123456789012345678901234567890123456789012345678901234567890 $! 1 2 3 4 5 6 7 $! $!Process copy of lock 6B002338 on system 0001002B $! $! We want to grab the File ID fields and the disk volume name from the resource name $! $ filn_start = 23 $ filx_start = 34 $ lbl1_start = 41 $ lbl2_start = 38 $ if this_is_VAX $ then $ filn_start = 19 $ filx_start = 30 $ lbl1_start = 39 $ lbl2_start = 36 $ endif $ lck_loop_1: $ read lis3 rec3 $!!! write sys$output "Looking for Resource:" !!! $!!! show symbol rec3 !!! $ if f$extract(0,9,rec3) .nes. "Resource:" then goto lck_loop_1 $ filn_hex = f$extract(filn_start,4,rec3) !File number in hex $!!! show symbol filn_hex !!! $!! filseq_hex = f$extract(19,4,rec3) !Sequence number in hex $ read lis3 rec3 $!!! show symbol rec3 !!! $ filx_hex = f$extract(filx_start,2,rec3) !File number extension in hex $!!! show symbol filx_hex !!! $!! rvn_hex = f$extract(32,2,rec3) !Relative Volume Number in hex $ disk_a = f$extract(lbl1_start,5,rec3) !First part of disk volume name $ filn = %x'filx_hex''filn_hex' !File number in decimal $!!! show symbol filn !!! $!! filseq = %x'filseq_hex' !Sequence number in decimal $!! rvn = %x'rvn_hex' !Relative volume number in decimal $ read lis3 rec3 $!!! show symbol rec3 !!! $ disk_b = f$extract(lbl2_start,7,rec3) !First part of disk volume name $ disk = f$edit(disk_a+disk_b,"TRIM") !Disk volume name $ close lis3 $ delete 'temp_file'_lis3;* $ dump/header/block=count=0/identifier='filn' /out='temp_file'_lis4 - DISK$'disk':[000000]INDEXF.SYS $!!! type/page 'temp_file'_lis4 !!! $ close/nolog lis4 $ open/read lis4 'temp_file'_lis4 $! $! Here's an example of what we're parsing: $! $!$dump/header/ident=217 disk$disk136:[000000]indexf.sys/block=count=0 $! $!Dump of file _DSA136:[136.DATA]HRARF1.W06;1 on 3-JAN-2007 18:16:04.07 $!File ID (217,1288,0) End of file block 1809 / Allated 1820 $! $! File Header $! $!Header area $! Identification area offset: 40 $! Map area offset: 100 $! Access control area offset: 245 $! Reserved area offset: 255 $! Extension segment number: 0 $! Structure level and version: 2, 1 $! File identification: (217,1288,0) $! Extension file identification: (0,0,0) $! VAX-11 RMS attributes $! Record type: Variable $! File organization: Indexed $! Record attributes: $! Record size: 0 $! Highest block: 1820 $! End of file block: 1810 $! End of file byte: 0 $! Bucket size: 2 $! Fixed control area size: 0 $! Maximum record size: 500 $! Default extension size: 0 $! Global buffer count: 100 $! Directory version limit: 0 $! File characteristics: Contiguous best try $! Caching attribute: Writethrough $! Map area words in use: 3 $! Access mode: 0 $! File owner UIC: [CONVERT1] $! File protection: S:RWED, O:RWED, G:RWED, W:RWED $! Back link file identification: (1425,2,0) $! Journal control flags: $! Active recovery units: None $! File entry linkcount: 0 $! Highest block written: 1820 $! Client attributes: None $! $!Identification area $! File name: HRARF1.W06;1 $! Revision number: 3395 $! Creation date: 15-DEC-2006 01:05:35.82 $! Revision date: 3-JAN-2007 07:17:01.82 $! Expiration date: $! Backup date: $! $!Map area $! Retrieval pointers $! Count: 1820 LBN: 168490 $! $!Access Control List $! (APPLICATION,SIZE=%D20,FLAGS=%X0E03,ACCESS=%X00010000,DATA=%X00140000, $! %X00010002,%X00000001) $! $!Checksum: 24623 $! $! All we're really interested in is the file specification, which DUMP nicely $! includes in its header, the "Dump of file" line $! (In version 8.3, I believe, there's an f$fid_to_name() lexical function $! which could replace all this nonsense) $ dmp_loop: $ read lis4 rec4 $ if f$extract(0,13,rec4) .nes. "Dump of file " then goto dmp_loop $ filespec = f$element(0," ",f$extract(13,99,rec4)) - "_" $ close lis4 $ delete 'temp_file'_lis4;* $ 'if_debug' write sys$output " File: ",filespec !!! $! Now examine the Global Buffer Descriptor Summary to see how many of the $! RMS Global Buffers present on the file are actually in use (or have been). $! $! Zero the counter/accumulators $ cnt_in_use = 0 $ cnt_used_before = 0 $ cnt_never_used = 0 $! Skip ahead to the Global Buffer Descriptor Summary output $ gbh_loop_1: $ read/end=cleanup lis rec $!!! write sys$output "Looking for GBD Summary" !!! $!!! show symbol rec !!! $ if f$edit(rec,"TRIM") .nes. "GBD Summary" then goto gbh_loop_1 $! Now, count the number of global buffers: $! - Currently in use (non-zero lock ID field and non-zero lock count) $! - Used at one point but not in use now (non-zero lock ID field but zero lock count) $! - Never used (zero lock ID field and zero lock count) $ gbdsum_loop: $ read/end=gbdsum_done lis rec $!!! show symbol rec !!! $ if f$extract(0,12,rec) .eqs. "GBH Address:" then goto gbdsum_done $! Skip heading lines, etc. but not data lines. $! Data lines have a blank first column. $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID MODE $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! 14266780 0000 0400 0400 0000002B 00000001 00021C00 0 71034790 1 CR $!or, for VAX 7.3: $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID FLAGS $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! 00049950 0 1024 1024 7 00000000 00006C00 2 73000DC5 $!01234567890123456789012345678901234567890123456789012345678901234567890 $! 1 2 3 4 5 6 7 $!Element:0 1 2 3 4 5 6 7 8 9 10 $!or, for Integrity 8.3-1H1: $! GBD USE BUFFER CACHE_ $! RELADDR CNT SIZE NUMB VBN VBNSEQNUM RELADDR VAL LOCK_ID MODE $!----------------- ---- ---- ---- --- -------- ---------------- --- -------- ---- $! $! 0000000000012480 0000 0400 0400 00000007 00000000 0000000000016400 3 6B0016EF 1 CR $! 0000000000012400 0000 0400 0400 00000004 0000006C 0000000000016000 0 2A0016EE 0 $! 0000000000012380 0000 0400 0000 FFFFFFFF 00000000 0000000000015C00 0 00000000 0 $!Element: 0 1 2 3 4 5 6 7 8 9 10 $ if f$extract(0,1,rec) .nes. " " then goto gbdsum_loop $ crec = f$edit(rec,"TRIM,COMPRESS") $ if f$length(f$element(5," ",crec)) .ne. 8 .or. - f$length(f$element(8," ",crec)) .ne. 8 then goto gbdsum_loop $! Now, detemine for each global buffer entry, whether its status is: $! 1) Currently in use $! 2) Not currently in use, but has been used in the past $! 3) Never yet used $! $! Currently in use (non-zero Lock ID and non-zero lock count): $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID MODE $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! 14266E00 0000 0400 0400 00000055 00000000 00025000 0 170CA67C 1 CR $! VAX 7.3: (non-zero Lock ID and non-zero CACHE_VAL) $! GBD USE REL_ CACHE_ $!Address CNT SIZE NUMB VBN VBNSEQNUM ADDR VAL LOCK_ID FLAGS $!------- ----- ---- ---- --- ------- ---- --- ------- ----- $! 00049950 0 1024 1024 7 00000000 00006C00 2 73000DC5 $! $! Used at one point but not in use now (non-zero Lock ID but zero lock count): $! 15F78D80 0000 0400 0400 000629C8 00000000 00014C00 0 68085F3B 0 $! VAX 7.3: (non-zero Lock ID but zero CACHE_VAL): $! 00049920 0 1024 1024 4 00000000 00006800 0 01002F89 $! $! Never used (zero Lock ID and zero lock count): $! 14265780 0000 0400 0000 FFFFFFFF 00000000 00019C00 0 00000000 0 $! VAX 7.3: (zero Lock ID and zero CACHE_VAL): $! 000498F0 0 1024 0 -1 00000000 00006400 0 00000000 $!Element:0 1 2 3 4 5 6 7 8 9 10 $ lckid = f$element(8," ",crec) $!!! show symbol lckid !Lock ID for global buffer $ lck_cnt = f$element(9," ",crec) $ if this_is_VAX then - lck_cnt = f$element(7," ",crec) $!!! show symbol lck_cnt !Count of locks on global buffer $ if lckid .nes. "00000000" $ then !If lock ID field is non-zero, buffer is in use or has been used before $ if lck_cnt .eqs. "0" $ then !No lock: buffer has been used but is not currently in use $ cnt_used_before = cnt_used_before + 1 $!!! write sys$output "This one was used before." !!! $ else !Lock present: buffer is currently in use $ cnt_in_use = cnt_in_use + 1 $!!! write sys$output "This one is in use." !!! $ endif $ else !If lock ID field is zero, buffer has never been used $ cnt_never_used = cnt_never_used + 1 $!!! write sys$output "This one has never been used." !!! $ endif $ goto gbdsum_loop $ gbdsum_done: $ cnt_total = cnt_in_use + cnt_used_before + cnt_never_used $ cnt_peak = cnt_in_use + cnt_used_before $!!! show symbol cnt_in_use !!! $!!! show symbol cnt_used_before !!! $!!! show symbol cnt_never_used !!! $!!! show symbol cnt_peak !!! $!!! show symbol cnt_total !!! $ 'if_debug' if cnt_used_before .eq. 0 $ 'if_debug' then $ 'if_debug' write sys$output " Global Buffers: ''cnt_in_use' in use, ''cnt_total' total." $ 'if_debug' else $ 'if_debug' write sys$output " Global Buffers: ''cnt_in_use' in use, ''cnt_peak' peak, ''cnt_total' total." $ 'if_debug' endif $ if f$length(filespec) .gt. 200 then - write sys$output "File Specification truncated: ",filespec $ write tmp f$fao("!200AS!10UL!10UL!10UL",- filespec,cnt_in_use,cnt_peak,cnt_total) $ goto gbh_loop $ cleanup: $ close lis $ delete 'temp_file'_lis;* $ delete 'temp_file'_err;* $ close tmp !Close temporary listing file $!!! type 'temp_file'_tmp/page !!! $! Eliminate duplicates of filespec (where multiple processes had a channel $! open to the same RMS file and thus the global buffer usage got reported $! multiple times) $ sort/key=(pos:1,size:200)/noduplicates 'temp_file'_tmp 'temp_file'_srt $ delete 'temp_file'_tmp;* !Delete temporary file $!!! type 'temp_file'_srt/page !!! $ close/nolog csv $ open/write csv global_buffer_usage_'date'_'nodename'.csv $ write csv - """File Specification"",""Current"",""Peak"",""Total""" $ open/read srt 'temp_file'_srt $ srt_loop: $ read/end=srt_eof srt rec $ filespec = f$edit(f$extract(0,200,rec),"TRIM") $ cnt_in_use = f$edit(f$extract(200,10,rec),"TRIM") $ cnt_peak = f$edit(f$extract(210,10,rec),"TRIM") $ cnt_total = f$edit(f$extract(220,10,rec),"TRIM") $ write csv - """",filespec,""",",cnt_in_use,",",cnt_peak,",",cnt_total $ goto srt_loop $ srt_eof: $ close srt $ delete 'temp_file'_srt;* !Delete temporary sort file $ close csv $ write sys$output "Results may be found in the file GLOBAL_BUFFER_USAGE_",date,- "_",nodename,".CSV" $ final_cleanup: $! If we turned on privileges, turn them off again $ if CMKRNL_TURNED_ON then set process/privilege=(noCMKRNL) $ if READALL_TURNED_ON then set process/privilege=(noREADALL) $ exit !Normal exit $! $! Exit due to an error $! $ error_exit: $ status = $status $ write sys$output "Some sort of error seems to have occurred." $ write sys$output "Error status is ",f$fao("!8XL",status) $ write sys$output "Error message is ",f$message(status) $ if f$search("''temp_file'_err") .nes. "" then write sys$output - "Check file ''temp_file'_err for error messages." $ goto final_cleanup