!fnlogarc.bsi [107] - Archive a log (or other) file using .?01, .?02, ... 
!-------------------.-------------------.-------------------.-------------------.
!EDIT HISTORY
! Note: history reformatted 15-Aug-17
! [107] 28-Apr-26 / jdm / Add keywords (for FUNCIDX)
! [106] 14-Mar-21 / jdm / option to preserve current file (copy instead of rename to .x01)
! [105] 27-Sep-20 / jdm / Switch from RENAME.SBR to MX_COPYFILE for more robust rename
! [104] 19-Sep-19 / jdm / Add Fn'LogRoll alias; upgrade traces
! [103] 20-May-19 / jdm / Eliminate unnecessary renames (fill in gaps);
! [102] 18-May-19 / jdm / add maxage params to Fn'LogArchive(); set maxsize default;
!                           disable file search path for logfile 
!                           (causes too much confusion)
! [101] 15-Aug-17 / jdm / handle filespecs with [p,pn] suffixes
! [100] 03-Jul-14 / jdm / created
!------------------------------------------------------------------------
!Keywords: logfile archive rollover
!------------------------------------------------------------------------

++ifnlbl Fn'LogArchive()

++include'once ashinc:types.def         ! [103]
++include'once sosfunc:fnfqfs.bsi       ! [101]
++include'once sosfunc:fnfileage.bsi    ! [102] 

defalias Fn'LogRoll() = Fn'LogArchive() ! [104] (more industry-standard)

!---------------------------------------------------------------------
! Function Name:   Fn'LogArchive
! Description:     Roll-over & archive a log file if > spec size
! Author:          Jack McGregor
! Date:            03-Jul-2014
!---------------------------------------------------------------------
!Parameters:
!   logfile$ (str) [in] - filespec of log file (AMOS or native)
!   maxsize (num) [in] - max size (bytes) before rollover (dflt 0)
!   maxgen (num) [in] - max # archived generations (default 5, max 999)
!   maxage (num) [in] - max age in days of oldest archived copy in days (dflt unlimited) [102]
!   preserve (BOOLEAN) [in] - if .TRUE, preserve current file (copy instead of rename to .x01 [106])
!Returns:
!   # of roll-overs (renames) performed (<0 # of errors)
!Globals:
!   No global vars
!Locals:
!   No other local vars
!Error handling:
!Notes:
!   Note that this can be used for non-log files. For example, when
!   updating RUNs, you might want to archive the prior ones using
!   the same R01, R02, ... scheme.  Just set maxsize to 0.
!
!   [102] Generation cycling stops when we reach the maxgens or
!   maxage, whichever comes first. So if you want to make sure you 
!   keep copies for at least N days, then set the maxgen to the 
!   maximum value (999). More typically, you might use a combination
!   of the two to make sure you have a reasonable time frame without
!   an unreasonable number of copies (say maxgen=50, maxage=90)
!--------------------------------------------------------------------

Function Fn'LogArchive(logfile$ as s260:inputonly, &
				maxsize=0 as f6:inputonly, maxgen=5 as b2:inputonly, &
                maxage=-1 as b4:inputonly, preserve=.FALSE as BOOLEAN:inputonly) as i2

trace.print (99,"fnlogarc") "Fn'LogArchive",logfile$,maxsize,maxgen,maxage
    map1 locals
        map2 fsize,f
        map2 lx,f
        map2 logarc1$,T_NATIVEPATH
        map2 logarc2$,T_NATIVEPATH
        map2 logarc3$,T_NATIVEPATH          ! [103]
        map2 status,f
		map2 curgen,i,2
		map2 errcnt,i,2
        map2 fileagedays,i,4                ! [102]
        map2 flags,b,4,CPYF_MOVE+CPYF_REPL  ! [106]
        
!>![102] replaced by default in param list		
!>!	if maxgen = 0 then
!>!		maxgen = 5
!>!	endif

    maxgen = maxgen min 999     ! [102] upper limit
	
    xcall SIZE,logfile$,fsize
    if fsize > maxsize then

        ! [101] if [p,pn], convert to native format to put .ext at the end
        ! [102] if instr(1,logfile$,"[") then
        ! [102] disable file search path by making filespec explicit
        logfile$ = Fn'FQFS$(logfile$)
        ! [102] endif

        lx = instr(1,logfile$,".")
        if lx = 0 then
            lx = len(logfile$)+1
            logfile$ = logfile$ + ".log"
        endif
		! lx -> "."
		for curgen = maxgen to 1 step -1
            if curgen < 100 then                                    ! [102] 
                logarc1$ = logfile$[1,lx+1] + (curgen using "#Z")
            else    
                logarc1$ = logfile$[1,lx] + (curgen using "#ZZ")    ! [102]
            endif
trace.print (99,"fnlogarc")  logfile$,logarc1$,lx,curgen
			if (curgen = maxgen) then	! remove max generation if present
				if lookup(logarc1$) kill logarc1$			
			endif
			if (curgen > 1) then
                if curgen < 101 then                                     ! [102] 
                    logarc2$ = logfile$[1,lx+1] + ((curgen-1) using "#Z")
                else    
                    logarc2$ = logfile$[1,lx] + ((curgen-1) using "#ZZ") ! [102]
                endif
			else
				logarc2$ = logfile$
			endif
trace.print (99,"fnlogarc")  logarc2$			
			if lookup(logarc2$) 

                ! [102] check for age limit
                if maxage > 0 then
                    fileagedays = Fn'FileAge(logarc2$, FILEAGE_MTIME) / 86400
trace.print (99,"fnlogarc")  fileagedays, maxage                        
                    if fileagedays > maxage then
                        kill logarc2$
                        repeat
                    else
                        maxage = 0      ! quit worrying about it after we get within limit
                    endif
                endif

                ! [103] before doing the rename, see if it's really necessary
                ! [103] (it's not if there is a gap prior to logarc2$)
                if (curgen > 2) then
                    if curgen < 102 then                      
                        logarc3$ = logfile$[1,lx+1] + ((curgen-2) using "#Z")
                    else    
                        logarc3$ = logfile$[1,lx] + ((curgen-2) using "#ZZ") 
                    endif
                    if lookup(logarc3$) = 0 then    ! if there's a gap, no need
                        repeat                      ! to rename logarc2
                    endif
                endif
                
				![105]  xcall rename,logarc2$,logarc1$,status
                
                if preserve and (curgen = 1) then   ! [106] if preserving current
                    flags = CPYF_REPL               ! [106] then make last rename a copy
                endif
                    
                xcall MIAMEX, MX_COPYFILE, logarc2$, logarc1$, flags, status
trace.print (99,"fnlogarc")  "rename",logarc2$,logarc1$,status
				if status then
					errcnt += 1
				else
					Fn'LogArchive += 1
				endif
			endif
		next curgen

    endif

	if errcnt then					! if any errors,
		Fn'LogArchive = -errcnt		! return error count 
	endif
	
EndFunction

++endif
