Bill Farrell
unread,Jul 20, 2012, 12:08:18 PM7/20/12Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to InterSy...@googlegroups.com, intersy...@googlegroups.com
Okay, here's the windup. I cloned off JRNDUMP into another .INT
routine. I then added an "X" (eXport) option to the "E"xamine submenu
when then calls the new code below. Yeah, I know it's not MV but if
you're in the fix we were in, not much MV code will do you a lot of
good. It is possible to convert this into a standalone MV routine and
deploy it in MGR %SYS. I don't see why you couldn't. I just haven't
had time yet. But since I opened a thread I figured I'd best come up
with an end to it :)
"D"o your modified JRNDUMP routine, select
the journal you want to work with and "E"xamine it just the way the
stock JRNDUMP works. Have your export option call the new code below.
When
you choose your export (mine is eXport), you get a device prompt since
the new tag calls %IS. (There is a note that gets sent to the screen
reminding you to choose “NWS” options if you output to a flat file.)
Next you’re prompted for strings to search for. Target strings will be
searched for both in the global and in the data. If either contains at
least one of the target strings and the record has either a Set or Kill
operator, it will be sent to the output file (or screen). No other
records will be output (no marks, no checkpoints, etc).
If you
enter no strings at the “Next string” prompt (just an empty return) or
if you hit “//” at any point in this prompt, the routine returns to the
previous set of options.
Whether output is to the screen or to a file, the output is the same when a target is found:
address <tab> process_id <tab> timestamp <tab> S/K <tab> global <tab> new_value
where:
address: the location in the log file where the record was found
process_id: the process id that caused the set or kill
timestamp: the $H-format date-time when the set or kill event occurred
S/K: (S)et or (K)ill
global: global location that was affected
new_value: if the operation was a Set, the new value that was inserted
Tab
characters are reasonably unlikely in data (but the delimiter is easy
to change) and easy to piece with. If tab is problematic we can always
change it to something else like, say, @vm ($c(253)) which ought to be
pretty uncommon on non-MV Cache. MV users will probably have to be a
bit more creative.
Since operations could be long, if you’re
outputting results to a file, there’s a busy-box that outputs a dot to
the screen every 1 second and every thirty seconds gives you a progress
stamp. Hopefully that’s enough to keep a VPN alive. That would look
something like:
Searching...
..............................
07/18/2012: Currently at 27272868, next address is 27272952, found 16 records.
...............................
07/18/2012: Currently at 56886240, next address is 56886328, found 16 records.
...............................
07/18/2012: Currently at 87775424, next address is 87775508, found 16 records.
.............
16 record(s) found.
<Enter> to continue
The contents of the file look like:
133384 574642506 62655,79602 K VAL(0,2,0,"P12014834",62474,0)
133440 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^JOB^ARVL0^P12014834^62474^^
133524 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^PRICE^ARPRICE^P12014834^62474^^
133612 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^LID^ARLID^P12014834^62474^^
133696 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^PRICE^ARPRICE^P12014834^62474^^
133784 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^PRICE^ARPRICE^P12014834^62474^^
133872 574642506 62655,79602 S VAL(0,2,0,"P12014834",62474,0) 1
133936 574642506 62655,79602 S VAL(0,2,0,"P12014834",62474,0,1) Ordered code (9999999) has been inactivated.
134040 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^JOB^ARVL0^P12014834^62474^^
134124 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^SPLIT^ARVSB^P12014834^62474^^
134212 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^ENDCT^ARVL0^P12014834^62474^^
134300 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^^AROEPC^P12014834^62474^^
134384 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^JOB^ARVL0^P12014834^62474^^
134468 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^VAL^NCXJBP^P12014834^62474^^
134556 574642506 62655,79602 S ERR(0,"P12014834") 62655,79602^ENDCT^ARVL0^P12014834^62474^^
134644 574642506 62655,79602 K ERR(0,"P12014834")
I'll warn right now: I'm an MV guy. My COS isn't the prettiest, but the routine does seem to work under fire.
Best,
Bill
;This tag only dumps forward from the current file cursor position. The "seek backward" capability
;from the original "find" tag has been removed since it makes no sense to dump transactions in reverse
;order. Multiple search strings may be entered. Enter an empty return to stop entering strings and
;proceed or enter // to exit this tag.
exportrec(addr) ;find a substring somewhere in the transaction log then export it to the output device.
New (addr)
s row=22, blank=$j("",80)
s GCount=0
s DotCount = 0
s htab = $Char(9)
; Capture the name of the terminal in case output goes to a file. This will allow the routine
; to switch easily to give progress reports.
s Term = $IO
w /cup(row+1,1),blank,/cup(row+1,1)
w /cup(row,1),blank,/cup(row,1)
d message("Note: If you plan to write the results to a file, use options ""NWS"".",3,row)
w /cup(row+1,1),blank,/cup(row+1,1)
w /cup(row,1),blank,/cup(row,1)
d ^%IS ; select a device
s ODevice=IO
w /cup(row,1),blank,/cup(row,1)
s StringList = "" ; list of strings to look for
u 0:(:"-S")
; clear the last two CRT rows
w /cup(row,1),blank,/cup(row,1)
w /cup(row+1,1),blank,/cup(row+1,1)
s StillEntering = 1
While StillEntering {
w /cup(row,1),blank,/cup(row,1)
r "Next string: ",str
s:str="//" str="" ; look for the "abandon" signal
q:str=""
; Add to the list of strings to look for.
i $ll(StringList)=0 {
s StringList = $lb(str)
} else {
s StringList = StringList _ $lb(str)
}
}
q:$ll(StringList)=0 ; empty string list
i str="//" Quit ; found the "abandon" signal
w /cup(row+1,1),blank,/cup(row+1,1)
w /cup(row,1),blank,/cup(row,1)
s rdy=$$YN("Ready","Y",0)
q:rdy="N"
w #,"Searching...",!
s a = addr, found = 0
s a =$ZUtil(78,17,a)
s Tick = $Piece( $H, ",", 2 )
s LastTick = Tick
While a'<0 { ; from first record up to EOF
s rec=$$thisrec(a,.glo,.val)
s op = $ZStrip($Piece(rec,"^",3),"*C") ; the operator is surrounded by weirdness
i "KkSs"[op { ; only looking for (S)ets or (K)ills
f Idx = 1:1:$ll(StringList) {
s str = $lg( StringList, Idx, "zzznotfoundzzz" )
i ($Get(glo)[str)!($Get(val)[str) { ; if the search string is located either in the node location or data value
s timestamp = $zu(78,24,a)
s PID = $zu(78,10,a)
; The record looks like: addr \t PID \t timestamp \t operation (s/k) \t global \t value
s ORec = a _ htab _ PID _ htab _ timestamp _ htab _ op _ htab _ glo _ htab _ val
i (ODevice'=Term) Use ODevice
w ORec,!
i (ODevice'=Term) Use 0
s GCount=GCount+1 ; keep track of progress
} ; if we got the operator we were looking for
}
}
i (ODevice'=Term) {
s Tick = $Piece( $H, ",", 2 )
i Tick = 1 Set LastTick = 0 ; we crossed midnight
i Tick > LastTick {
s DotCount = DotCount + 1
u 0
i (DotCount>30),(ODevice'=Term) {
s RightNow=$ZTIME($PIECE($HOROLOG,",",2),1)
w !,RightNow,": Currently at ", Lasta _ ", next address is " _ a, ", found ", GCount, " records.",!
s DotCount = 0
}
w "."
s LastTick = Tick
}
}
s Lasta = a ; remember the last address
s a = $ZUtil(78,17,a)
q:Lasta'<a
}
i (ODevice'=Term) Close ODevice u 0
w !!,$Justify(GCount,8)_" record(s) found.",!
r !,"<Enter> to continue",dummy:300
w #
q