› Clovertech Forums › Read Only Archives › Cloverleaf › Cloverleaf › CRON jobs, TCL, and HCI all intermingling
1. I need to stop the outbound thread to prevent messages from being written to the file while it is being moved, so I will need to call hci commands from a TCL script. I think using the Upoc protocol to call the tcl script rather than using a CRON job is better since I would have to modify the profile for CRON to be able to call the hci commands with the tcl interpreter.
2. I can leverage the
I have done this many times. Really no need for stopping the thread.
Setup the OB thread as both a read and write UPoC protocol using the same proc in both places
In the proc run mode simply write messages to the file. In the time mode, which could be advanced scheduling or not, check to see if it is time to move the file. If so move it if not do nothing
There is no danger of writing to the file while moving since both the read and write cannot run at the same time
Just a quick idea, it would be safer, and more efficient, to move (DOS-RENAME, UNIX-mv) the file vs. copying it and clearing it.
Robert Milfajt
Northwestern Medicine
Chicago, IL
Here is something that I had written a while back. It probably does a bit more then u want (for example, it ftp’ed a file over to a server and also did some file header stuff) u can just remove that part. The thread that was writing messages to a file was called pcm_a_out. The example below checks to see the status of that thread and if it running, it will stop it, move the file away and turn it back on.
######################################################################
# Name: ftpEpicAdtToPatientCallManager
# Purpose:
# UPoC type: tps
# Args: tps keyedlist containing the following keys:
# MODE run mode (”start”, “run”, “time” or “shutdown”)
# MSGID message handle
# CONTEXT tps caller context
# ARGS user-supplied arguments:
#
#
# Returns: tps disposition list:
#
#
# Notes:
#
# History: MM/DD/YYYY Programmer Modification
# ———- ———- ————
# 09/27/2012 R. Masood Initial creation
package require ftp
proc ftpEpicAdtToPatientCallManager { args } {
global HciSite HciConnName HciSiteDir
keylget args MODE mode ;# Fetch mode
set ctx “” ; keylget args CONTEXT ctx ;# Fetch tps caller context
set uargs {} ; keylget args ARGS uargs ;# Fetch user-supplied args
set debug 0 ; ;# Fetch user argument DEBUG and
catch {keylget uargs DEBUG debug} ;# assume uargs is a keyed list
set module “ftpEpicAdtToPatientCallManager/$HciConnName/$ctx” ;# Use this before every echo/puts,
;# it describes where the text came from
set dispList {} ;# Nothing to return
switch -exact — $mode {
start {
# Perform special init functions
# N.B.: there may or may not be a MSGID key in args
if { $debug } {
puts stdout “$module: Starting in debug mode…”
}
}
run {
# ‘run’ mode always has a MSGID; fetch and process it
keylget args MSGID mh
lappend dispList “CONTINUE $mh”
}
time {
# Timer-based processing
# N.B.: there may or may not be a MSGID key in args
puts “*** UPLOAD PROCESS STARTED ***”
set ftphostname “ftp.server.com”
set ftpusername “username”
set ftppassword “password”
set now [clock format [clock seconds] -format “%m%d%Y”]
if { [lsearch -exact [ls $HciSiteDir/exec] monitorShmemFile] == -1 } { exit }
if { [catch {set PCMmsiTocEntry [msiTocEntry “pcm_a_out”]}] } {
catch {msiAttach}
set PCMmsiTocEntry [msiTocEntry “pcm_a_out”]
}
set PCMThreadStatus [keylget PCMmsiTocEntry ALIVE]
set oldadtfile “/data/healthvision/cis5.8/integrator/s_his/data/pcm/pcm_a_out.txt”
set tmpadtfile “[file rootname $oldadtfile].${now}.tmp[file extension $oldadtfile]”
if { $PCMThreadStatus } {
puts “… stopping thread (pcm_a_out) …”
catch {exec hcicmd -p “epic_adt_01” -c “pcm_a_out pstop”}
if { [file exist $oldadtfile] } {
puts “… renaming file ($oldadtfile) to a temporary location ($tmpadtfile)”
file rename -force $oldadtfile $tmpadtfile
}
puts “… starting thread (pcm_a_out)”
catch {exec hcicmd -p “epic_adt_01” -c “pcm_a_out pstart”}
} else {
puts “Thread (pcm_a_out) was not running …”
if { [file exist $oldadtfile] } {
puts “… Renaming file ($oldadtfile) to a temporary location ($tmpadtfile)”
file rename -force $oldadtfile $tmpadtfile
}
}
if { [file exist $tmpadtfile] } {
set upladtfile “[file dirname $oldadtfile]/EPIC_ADT_TO_PCM_${now}.dat”
set hdradtfile “[file dirname $oldadtfile]/PCM_Header.dat”
puts “… making a copy of header file ($hdradtfile) so we can append data to it ($upladtfile)”
file copy -force $hdradtfile $upladtfile
puts “… appending data from temporary file ($tmpadtfile) to the file that will be uploaded ($upladtfile)”
set rfileptr [open $tmpadtfile]
set wfileptr [open $upladtfile a]
while { [gets $rfileptr line] >= 0 } {
puts $wfileptr $line
}
close $rfileptr
close $wfileptr
puts “… deleting temporary file ($tmpadtfile)”
file delete -force $tmpadtfile
if {[set conn [ftp::Open $ftphostname $ftpusername $ftppassword]] == -1} {
puts “Could not connect to the ftp server ($ftphostname) … ”
return
}
puts “… uploading upload file ($upladtfile)”
ftp::Put $conn $upladtfile
ftp::Close $conn
set newadtfile “[file dirname $oldadtfile]/EPIC_ADT_TO_PCM_${now}.sent.dat”
puts “… saving upload file with new name ($newadtfile)”
file rename -force $upladtfile $newadtfile
}
puts “*** UPLOAD PROCESS ENDED ***”
}
shutdown {
# Doing some clean-up work
}
default {
error “Unknown mode ‘$mode’ in $module”
}
}
return $dispList
}
For situations like this, I’ve used a datestamp suffix on the file name.
I let the TCL proc manage the file naming.
something like:
set cs [clock seconds]
set suffixHour [expr ([clock format $cs -format “%H”] / 12) * 12]
set day [clock format $cs -format “%Y%m%d”]
set currentFileName [format “yourFile_%s%02d00.xyz” $day $suffixHour]
Just open the file in append mode each time and write your current message to it.
.
set outFile [open [file joing /yourDir $currentFileName] a]
puts $outFile $msg
close $outFile
Then, find any files in your current write directory that are NOT the current file name, and move them to the location where they’re to be picked up.
set fileNames [glob -nocomplain -tails -directory /yourDir *]
foreach f $fileNames {
if { $f ne $currentFileName } {
file rename -force [file join /yourDir $f] [file join /otherDir $f]
}
}
Your time mode and/or run mode can do the file move. The drawback to doing it in the run mode is that you’re reliant on receipt of a message to trigger it.
I generally make an archive copy for future reference before placing it in the pickup location.
You’d also want to ensure that from/to directories exist and may want to use catch to protect against failures – particularly with the file read/write/rename functions.
With this approach, you don’t need to be concerned with moving a file that’s being written and, with an archive copy, you can keep track of what was sent and when it was sent.
Jeff Dinsmore
Chesapeake Regional Healthcare