OPEN.FILE
From Pickwiki
Jump to navigationJump to search function OPEN.FILE( FILENAME, FLAGS, FILEVAR, ERR.MSG )
* Return File handle: open file and keep file variable in Named Common or just return it.
* =======================================================================================
* 19.Jan.2012 james: Check if FLAGS is assigned to avoid errors going to the log.
* 31.Jan.2009 james: Major restructuring: Let's USE this thing !?
* 08.Feb.2008 james: Finally doing this the right way !? (From U2 Users maillist, etc).
* =======================================================================================
*
* This is a hybrid of version from U2 Users group list and APP.PROGRS OPEN.FILE.B
* (we don't want to use the UV version anyway in case we switch to Cache?)
*
* Usage:
*
* if not( OPEN.FILE("MYFILE", FLAGS, MYFILEVAR, ERR.MSG) ) then <error handling using ERR.MSG>
*
* ---------------------------------------------------------------------------------------
*
* In :
* FILENAME
* FLAGS : 'RESET' to reset COMMON.OPEN.FILE; not normally used.
*
* Out:
* FILEVAR : Return the regular UV 'File Variable' used to READ[[/WRITE/etc]].
* ERR.MSG : If returned non-blank THERE'S A PROBLEM
*
*
* @TODO :
*
* - Replace all 'OPEN' statements with call to this program !!!!
*
* - Enable commented code in REP.WRITE '[[OpenLocalFile]]' to use this instead.
*
* - Comment out (make 'ununsed' ?) R$[[LOCAL_FILE_NAME_S]], etc, in REPLICATION.COMMON
*
* - Once this is being called everywhere, we can REMOVE the 'Common' opens in STD.SETUP.
*
* =======================================================================================
$include RMS.BP RMS.COMMON ;* DEBUG.FLAG to check for 'OPEN.FILE' flag.
$include UTIL.BP COMMON.OPEN.FILE
ERR.MSG = ""
OK = @TRUE ;* Assume we get the file opened until proven otherwise.
if not( assigned( FLAGS ) ) then FLAGS = '' ;* Avoid errors: not normally used anyway.
locate 'OPEN.FILE.LOG' in FLAGS<1> setting dum then [[OpenFileLog]] = @TRUE else [[OpenFileLog]] = @FALSE
gosub [[CheckResetCommon]] ;* Set '[[ResetCommon]]' but do it later (so we can log it if necessary):
* --- Setup logging flag :
locate "OPEN.FILE.LOG" in DEBUG.FLAG<1> setting dummy then
[[OpenFileLog]] = @TRUE
[[OpenFileLogName]] = "/var/log/uv_OPENFILE.log"
end else [[OpenFileLog]] = @FALSE
* --- Reset the first time this is called _OR_ if we've switched UV Accounts:
if [[ResetCommon]] then gosub [[ResetOpenFileCommon]]
if FILENAME # '' then ;* Send '' for dummy options (e.g. 'RESET')
* --- Finally: If we have the File open already, then return the cached FILEVAR:
* (use FM locate since it may be optimized ? TEST IT ?)
if not( OF$USE.CACHE ) then ;* The hard way for testing:
OF$FILE.POS = 1 ; gosub [[OpenNewFile]]
end else
locate(FILENAME, OF$FILENAME.S; OF$FILE.POS) then ;* Already open ?:
[[LogMsg]] = "File ":FILENAME:" is already open in position ":OF$FILE.POS ; gosub [[WriteLog]]
FILEVAR = OF$FILEVAR.S( OF$FILE.POS )
end else
gosub [[OpenNewFile]]
end
end
OF$LAST.OPENED = FILENAME
OF$LAST.OPENED.POS = OF$FILE.POS
end
return( OK )
* --- Check if we need to Reset the commons: if this is the first time this is run; or
* if the RESET flag is sent in.
[[CheckResetCommon]]:
[[ResetCommon]] = @FALSE ;* This may still get set below too
locate "RESET" in FLAGS<1> setting dummy then ;* Special flag to clear Global Common
[[ResetCommon]] = @TRUE
end else
if not( assigned( OF$USE.CACHE ) ) then
[[ResetCommon]] = @TRUE
end else ;* And also reset if we change Accounts (LOGTO) :
if OF$CURRENT.ACCOUNT # @WHO then [[ResetCommon]] = @TRUE
end
end
return ('')
[[ResetOpenFileCommon]]:
[[LogMsg]] = "Clearing Global Common OPEN.FILE" ; gosub [[WriteLog]]
OF$FILENAME.S = '' ;* Reset the dynamic array of File Names
mat OF$FILEVAR.S = '' ;* This is not strictly necessary but may help hiding bugs
OF$CURRENT.ACCOUNT = @WHO ;* Keep track of the current UV Account
mat OF$ITEM.ID.S = ''
mat OF$ITEM.S = ''
OF$LAST.OPENED = ''
OF$LAST.OPENED.POS = 0
open "CONTROL" to CONTROL.FILE else stopm "Unable to open CONTROL file"
read OF$USE.CACHE from CONTROL.FILE, "USE.OPEN.FILE.CACHE" else OF$USE.CACHE = @TRUE
return ('')
* Open it first; so we let it open normally even if it can't be cached : (?)
[[OpenNewFile]]:
open FILENAME to FILEVAR else
ERR.MSG = 'Unable to open ':FILENAME ; [[LogMsg]] = ERR.MSG ; gosub [[WriteLog]]
OK = @FALSE ; return('')
end
if OF$FILE.POS > MAX.OPEN.FILES then
ERR.MSG = 'TOO MANY FILES OPEN !?' ; OK = @FALSE
if [[OpenFileLog]] then [[LogMsg]] = ERR.MSG ; gosub [[WriteLog]]
end else
[[LogMsg]] = "Opening ":FILENAME:" in position ":OF$FILE.POS ; gosub [[WriteLog]]
OF$FILENAME.S< OF$FILE.POS > = FILENAME ;* VM's to use standard Locate
OF$FILEVAR.S( OF$FILE.POS ) = FILEVAR
OF$ITEM.ID.S( OF$FILE.POS ) = '' ;* The LAST Id ONLY for READ.FILE
OF$ITEM.S ( OF$FILE.POS ) = '' ;* The LAST item ONLY for READ.FILE
end
return ('')
* This writes a Log file if '[[OpenFileLog]]' is set; also displays if '[[DebugIt]]' is set:
[[WriteLog]]:
*if [[DebugIt]] then crt [[LogMsg]] ;* input j ; if j = 'D' then debug
if [[OpenFileLog]] then
* We don't have 'CALLER' here like REP.WRITE; would it be useful ? We can get the PID though:
[[LogMsg]] := ' (':USER.ID:'; pid:':RMS$PID:')' ;* PID now set in STD.SETUP
call APPEND.UNIX.LOG( [[LogMsg]], [[OpenFileLogName]], [[AppendErr]])
if [[AppendErr]] # '' then
ERR = "Unable to Append to Log file ":[[OpenFileLogName]]:" !"
crt char(7):ERR
ERR.MSG := ERR ;* Add to existing ERR.MSG if there ?
end
end
return ('')