OPEN.FILE
From Pickwiki
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 ('')