Google
 

Trailing-Edge - PDP-10 Archives - DEC_CMS-20_V1.0_SRC - cms/sources/transa.bli
There are no other files named transa.bli in the archive.
module transa (! Define a transaction for crash recovery.
		ident = '1',
		%if
		    %bliss(bliss32)
		%then
		    language(bliss32),
		    addressing_mode(external=long_relative,
				    nonexternal=long_relative)
		%else
		    language(bliss36)
		%fi
		) =
begin

!
!			  COPYRIGHT (C) 1982, 1983 BY
!	      DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
! ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH  LICENSE AND WITH THE
! INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR  ANY  OTHER
! COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
! OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
! TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE  WITHOUT  NOTICE
! AND  SHOULD  NOT  BE  CONSTRUED  AS  A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF  ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!

!++
! Facility:  CMS Library Processor
!
! Abstract:
!
!	The routines in this module are called to define the start and
!	finish of a library transaction for crash recovery purposes.
!	Another routine gives files the desired characteristics to enable
!	recovery.
!
! Environment:  Transportable
!
! Author:  Earl Van Horn	Creation Date:  January 3, 1980
!
!--
!
! Table of Contents:
!
forward routine
    begtrn : novalue,		! Start a library transaction.
    cantrn : novalue,		! Cancel a library transaction.
    endtrn : novalue,		! Finish a library transaction.
    bad_to_fin : novalue,	! Rename bad file to fin file
    logtim,			! Get the transaction time for the log.
    nowtrn,			! TRUE if transaction in progress.
    numtrn,			! Number of library transactions completed
    oldtrn,			! TRUE if previous transaction incomplete.
    trnfil : novalue,		! Set characteristics for a transaction file.
    trntim : novalue ;		! Get the official time of this transaction.

!
! Include Files:
!
%if %bliss(bliss32) %then
   library 'sys$library:starlet';
%else
   require 'JSYS:' ;
%fi
library 'XPORT:' ;
require 'BLISSX:' ;
require 'FILUSR:' ;
require 'SCONFG:' ;
require 'SHRUSR:' ;
require 'TIMUSR:' ;
require 'ZONUSR:' ;
require 'cncusr:' ;
!
! Macros:
!

!
! Equated Symbols:
!

!
! Own Storage:
!
own
    $io_block(bbad),				! IOB for the file which
						! permanently records that
						! a transaction is in progress.
    $io_block(rep),				! repair file means repair in
 						! progress.
    group_library : initial(true),		! Means people in the user's
						! group can use the library.
    log_file_set,				! TRNFIL has set the
						! characteristics of the log.
    number_of_transactions : volatile initial(0),! Number of completed
						! transactions.  This is
						! declared VOLATILE because it
						! is used indirectly by CNTRLC.
    transaction_time : time_block,		! The revision time to be given
						! to all files in this
						! transaction.
    transaction_in_progress : volatile initial(false),! Means a library
						! transaction is currently
						! underway.  This is declared
						! VOLATILE because it is used
						! indirectly by CNTRLC.
    trnzon : new_zone,				! Zone that is flushed at the
						! end of a transaction.
    world_library : initial(false) ,		! Means anyone can use the
						! library.
    f_cty_dis : initial(0);			!cty already disabled

!
! External References:
!
external
    f_rb_pending,		! Indicates the transaction is not yet committed
    				! and is used by the roll back mechanism(ROLBCK)
    f_rb_clspd,			! Indicates the transaction is committed and
    				! is used by the roll back mechanism(ROLBCK)
    f_lib_modified,		! Indicates if any files in library have been modified,
				!   used to tailer error messages
    repair;			! indicates whether a verify/repair is the present transaction

external routine
    asctim,			! Get the ASCII form of a binary time.
    badbug,			! report unrecoverable error (ERRMSG)
    badiob : novalue,		! Report a library problem involving an iob.
    badlib : novalue,		! Report a problem with the project library.
    bug : novalue,		! Report a bug.
    bugiob : novalue,		! Report a bug involving an iob.
    curtim : novalue,		! Get current time in binary.
    delvrs,			! Delete versions of a file.
    dirspc : novalue,		! Extract the directory portion of a spec.
    donlib : novalue,		! Release the library.
    gen_lim,			! reset file version number
    isdir,			! Find directory and test if it's the library.
    isfile,			! Test if a file exists.
    libini,			! Value means library is being initialized.
    librea,			! Value means library is secure for reading.
    libwri,			! Value means library is secure for writing.
    mrkrev : novalue,		! Set file revision time and mark the file.
    nateql,			! Compare file specs. for equal names & types.
    protec : novalue,		! Set protection codes for a file.
    revmrk,			! Get revision time of a file.
    say,			! tell user something
    timcop : novalue,		! Copy time block value to another time block.
    timinc : novalue,		! Increase a time by some number of seconds.
    timleq,			! Compare two times.
    trylib,			! Try to obtain the library, but do not wait.
    zflush ;			! Free up the contents of a zone.
global routine begtrn : novalue =

!++
! Functional Description:
!
!	This routine starts a library transaction by noting this fact in the
!	library so that recovery will be demanded if a crash occurs.  It may
!	not be called again until ENDTRN or CANTRN has been called.
!
!	It establishes the official transaction time for this transaction,
!	for use by TRNFIL.  The official time is strictly greater
!	than that of the previous transaction time, which is the revision
!	time of a specific control file.  Thus the official times always
!	increase, even if the operator sets back the system time.
!
!	The time to be used in the log file is derived from the official
!	transaction time, using LOGTIM declared in this module.  The official
!	time is made sufficiently greater than the previous time, so that the
!	times in the log file will be distinct, and so that each will
!	correspond to just one transaction.  This is necessary so that a
!	nullified transaction can be marked in the log and ignored.
!
!       A repair file is also maintained to determine if updated files are
!       to be rolled back (non-repair) or not.  If a repair transaction is
!       in progress the repair file is created otherwise it is deleted if it
!       exists.
!
! Formal Parameters:
!
!	none
!
! Implicit Inputs:
!
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!       The external variable repair indicates if this is a VERIFY/REPAIR
!
! Implicit Outputs:
!
!	The variable LOG_FILE_SET declared OWN in this module.
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!	The time block TRANSACTION_TIME declared OWN in this module.
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	The library is modified to indicate that a transaction is in progress.
!
!--

    begin	! BEGTRN
    local
	by_step,			! Means a file was closed by CMS.
	lib_fil_vers,			! library file version retention count
	minimum_time : time_block,	! Minimum time for this transaction.
	previous_time : time_block ;	! Time of last transaction.

    ! Check the sequencing of this and related calls.
    if not libwri()
    then
	bug(lit('BEGTRN was called with the library not writable')) ;
    if .transaction_in_progress
    then
	bug(lit('Unnecessary call to BEGTRN')) ;

    !+
    ! Determine the one official time for this transaction.  It must be
    ! strictly greater than the time of the last transaction, even if
    ! the operator has set back the system time.  For proper resolution of
    ! times in the log file, it must be at least one second greater.
    ! To allow for possible changes in the binary to ascii time conversion
    ! algorithms, it must be at least 3 seconds greater.  For safety, 
    ! it will be made 5 seconds greater.
    !-
    ! If the bad file already exists then we are trying to recover
    ! an unsuccessful repair by faking a complete transaction.
    ! that way all times etc sill be sucessful
    !-
    IF isfile(len_comma_ptr(%string(lib, bad)), k_null)
    THEN
 	BEGIN
 	revmrk(len_comma_ptr(%string(lib,bad)), transaction_time, by_step);
 	transaction_in_progress = true ;
 	RETURN;
 	END;

    ! Use the current time if possible.
    curtim(transaction_time) ;

    ! Unless we are initializing the library, there was a previous transaction.
    if not libini()
    then
	begin	! Previous transaction.

	! Previous transaction time is the finished file's revision time.
	if not revmrk(len_comma_ptr(%string(lib,fin)), previous_time, by_step)
	then
	    badlib(cat('Transaction completion file does not exist')) ;

	! Make sure the FIN file was closed by CMS.
	if not .by_step
	then
	    badlib(cat(%string('Transaction completion file ',
			       'was not closed by ',fac_name))) ;

	! Add five seconds to the previous time to get the minimum time.
	timinc(previous_time, 5, minimum_time) ;

	! The transaction time must be at least the minimum time.
	if not timleq(minimum_time, transaction_time)
	then
	    timcop(minimum_time, transaction_time) ;		

	end ;	! Previous transaction.

    !+
    ! Now record the start of this transaction.
    !-

    ! Note that a transaction has been started by this process.  This must
    ! be done before creating the BAD file, so that CNTRLC will get a correct
    ! response from NOWTRN.
    transaction_in_progress = true ;
    !+
    ! indicate whether a repair is in progress or not
    !-
    IF
 	.repair
    THEN
 	BEGIN
        IF
 	    NOT $step_open(iob = rep_iob,
 			   file_spec = %string(lib, repr),
			   options = append, failure = 0)
    	THEN
	    badiob(rep_iob, lit(%string('Can not create ', lib, repr))) ;
 	trnfil(rep_iob);
 	IF
 	    NOT $step_close(iob = rep_iob, options = remember)
 	THEN
            badiob(rep_iob, lit(%string('Can not close ', lib, repr))) ;
 	END
    ELSE
        delvrs(0, len_comma_ptr(%string(lib, repr))) ;
        
    ! Create the file indicating a transaction in progress.
    if step$_created neq $step_open(iob = bbad_iob, file_spec = %string(lib, bad),
				options = append, failure = 0)
    then
	badiob(bbad_iob, lit(%string('Can not create ', lib, bad))) ;

    ! Initialize TRNFIL for this transaction.
    log_file_set = false ;

    ! Have the right transaction time and protection code set upon close.
    trnfil(bbad_iob) ;

    ! Close the file so it is secure on the disk during the transaction,
    ! but remember it for efficient renaming by ENDTRN.
    if not $step_close(iob = bbad_iob, options = remember)
    then
	badiob(bbad_iob, lit(%string('Can not close', lib, bad))) ;

    end ;	! BEGTRN
global routine cantrn : novalue =

!++
! Functional Description:
!
!	This routine cancels a library transaction.  It changes
!	the library so that no recovery will be demanded if a crash occurs.
!	It must be called only once after each call to BEGTRN.
!
!	In this implementation, it is assumed that the caller has cleaned up,
!	i.e., that the caller has deleted all files that were tentatively
!	created as part of the transaction being canceled.  Also, the log file
!	must not have been updated.  CANTRN will report a bug if TRNFIL was
!	called for the log file in this transaction.
!
! Formal Parameters:
!
!	None
!
! Implicit Inputs:
!
!	The variable LOG_FILE_SET declared OWN in this module.
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!
! Implicit Outputs:
!
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	The library is changed so that recovery will not be demanded.
!
!--

    begin	! CANTRN

    ! Check the sequencing of calls.
    if not .transaction_in_progress
    then
	bug(lit('CANTRN called before BEGTRN')) ;

    ! Make sure TRNFIL has not been called for the log file.  This gives some
    ! assurance that the log file has not been updated.
    if .log_file_set
    then
	bug(lit('CANTRN says TRNFIL was called for the log file')) ;

	!+
	!   Unconditionally disable CTRL/C interrupts
	!-
    disable_ctl_y;

    ! Delete the file that indicates a transaction is in progress.
    if not $step_delete(iob = bbad_iob, failure = 0)
    then
	badiob(bbad_iob, lit(%string('Can not delete ', lib, bad))) ;

    ! Allow another BEGTRN.  This must occur after the BAD file is deleted,
    ! so NOWTRN will not get confused.
    transaction_in_progress = false ;

    ! toggle ROLBCK flags
    f_rb_clspd = true ;
    f_rb_pending = false ;
    f_lib_modified = false;
    
	!+
	!   Unconditionally re-enable CTRL/C interrupts
	!-

    enable_ctl_y;

    end ;	! CANTRN
global routine endtrn : novalue =

!++
! Functional Description:
!
!	This routine defines the end of a successful library transaction.
!	It changes the library so that no recovery will be demanded if a crash
!	occurs.  It must be called only once after each call to BEGTRN.
!
!	TRNFIL must be called for the log file before ENDTRN is called for
!	the current transaction.
!
! 	If a repair transaction is being ended the repair file is deleted.
!
! Formal Parameters:
!
!	none
!
! Implicit Inputs:
!
!	The variable LOG_FILE_SET declared OWN in this module.
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!	The variable NUMBER_OF_TRANSACTIONS declared OWN in this module.
!
! Implicit Outputs:
!
!	The variable TRANSACTION_IN_PROGRESS declared OWN in this module.
!	The variable NUMBER_OF_TRANSACTIONS declared OWN in this module.
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	The library is changed so that recovery will not be demanded.
!
!--

    begin	! ENDTRN

    ! Check the sequencing of calls.
    if not .transaction_in_progress
    then
	bug(lit('ENDTRN called before BEGTRN')) ;

    ! Make sure TRNFIL has been called for the log file.  This gives some
    ! assurance that the log file has been updated.
    if not .log_file_set
    then
	bug(lit('ENDTRN says TRNFIL was not called for the log file')) ;

    ! Count the number of completed transactions before deleting the BAD
    ! file.  This assures that CNTRLC will say the transaction is either
    ! in progress or done.  If transactions were counted after deleting
    ! the BAD file, there would be a window in which it would look to CNTRLC
    ! like the transaction has not yet started.
    number_of_transactions = .number_of_transactions + 1 ;

    disable_ctl_y;
    f_cty_dis = true;

    !rename the bad to the fin
    bad_to_fin();

    !+
    !   ROLBCK CODE: The fin file is renamed successfully at this point.
    !   Thus the appropriate flags in the ROLBCK Module must be toggled
    !   to indicate the switch from a uncommitted to a committed transaction.
    !-

    f_rb_pending = false ;	! uncommitted rolbck flag
    f_rb_clspd = true ;    	! Committed transaction rolbck flag
    f_lib_modified = false;

    enable_ctl_y;

    ! Allow another BEGTRN.  This must occur after the BAD file is deleted,
    ! so NOWTRN will not be confused.
    transaction_in_progress = false ;

    end ;	! ENDTRN
global routine bad_to_fin : novalue =

!++
! Functional Description:
!
!	This routine renames the bad file to the fin file thus marking the
!       sucessful end of a transaction. On a repair the repair file is deleted.
!
! Formal Parameters:
!
!	none
!
! Implicit Inputs:
!
!	none
!
! Implicit Outputs:
!
!	none
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	The library is changed so that recovery will not be demanded.
!
!--

    begin	! BAD_TO_FIN


    !+
    !   Unconditionally disable CTRL/C interrupts
    !-
	        
    disable_ctl_y;


    ! Rename the file that indicates a transaction is in progress.
    ! The revision date and time of the renamed file is used by BEGTRN
    ! to determine the official transaction time of the next transaction.

    if not $step_rename(iob = bbad_iob,
 			file_spec = %string(lib, bad),
 			new_spec = %string(lib, fin),
			failure = 0)
    then
	begin
	!See if file version number is too large
	if
	    (%if VaxVms %then
	     .bbad_iob[iob$g_2nd_code]  eql ss$_badfilever
	     %fi
	     %if Tops20 %then
	     .bbad_iob[iob$g_comp_code] eql gjfx20 ^ 3
	     %fi)
	then
	    !00fac_name.fin version number is too high
	    begin
	    local
		fin_fil : desc_block;

	    $str_desc_init(descriptor=fin_fil,string=%string(lib,fin));
	    if
		not gen_lim(fin_fil)
	    then
		badiob(bbad_iob, lit(%string('Can not rename ', lib, bad))) ;

	    !try the rename one more time
	    $io_block_init(bbad);
	    if
		not $step_rename(iob = bbad_iob, file_spec = %string(lib,bad),
				      new_spec = %string(lib, fin),
				      failure = 0)
	    then
		badiob(bbad_iob, lit(%string('Can not rename ', lib, bad))) ;
	    end
	else
		badiob(bbad_iob, lit(%string('Can not rename ', lib, bad))) ;
	end;


    !+
    !   Unconditionally re-enable CTRL/C interrupts
    !-
    IF NOT .f_cty_dis
    THEN
 	enable_ctl_y;	    

    !+
    ! for a repair delete the repair file
    !-
    delvrs(0, len_comma_ptr(%string(lib, repr))) ;

    ! Purge the previous versions of the FIN file.
    delvrs(filvrs, len_comma_ptr(%string(lib, fin))) ;

    ! Delete any XXX files created by this user.  These are files that
    ! VERIFY/RECOVER wanted to delete, but could not because it did not
    ! have permission.
    delvrs(0, len_comma_ptr(%string(lib, xxx))) ;

    end ;	! ENDTRN
global routine logtim(p_buffer) =

!++
! Functional Description:
!
!	This routine returns the ASCII form of the current official
!	transaction time.  This is the string that must be used in the log
!	file to support crash recovery.
!
!	This routine must be called after BEGTRN, but not after ENDTRN or
!	CANTRN, unless BEGTRN is called again.
!
! Formal Parameters:
!
!	p_buffer:	Character pointer to the first character of a buffer
!			having at least 24 characters.  The date and time in
!			form DD-MMM-YY HH:MM:SS is stored left adjusted in the
!			buffer, and the remaining characters are undefined.
!
! Implicit Inputs:
!
!	The own variable TRANSACTION_IN_PROGRESS declared in this module.
!	The own variable TRANSACTION_TIME declared in this module.
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	The number of characters in the date-time string that was stored
!	left-adjusted in the buffer.
!
! Side Effects:
!
!	None
!
!--

    begin	! LOGTIM

    ! Make sure there is a transaction in progress.
    if not .transaction_in_progress
    then
	bug(lit('LOGTIM called with no transaction in progress')) ;

    ! Convert the official transaction time.
    asctim(transaction_time, .p_buffer)

    end ;	! LOGTIM
global routine nowtrn =

!++
! Functional Description:
!
!	This routine returns TRUE if and only if there is a transaction
!	currently being made in this process.  This means that BEGTRN has
!	been called, but the corresponding call to ENDTRN or CANTRN has not
!	occurred.
!
! Formal Parameters:
!
!	None
!
! Implicit Inputs:
!
!	TRANSACTION_IN_PROGRESS declared own in this module.
!	The existence or absense of 00fac_name.BAD.1 in the library.
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	See functional description.
!
! Side Effects:
!
!	None
!
!--

    begin	! NOWTRN

    !+
    ! CNTRLC uses NOWTRN to determine whether the library will have to
    ! be recovered if the user does not continue.  Therefore, the presense
    ! of the BAD file is tested.  To insure that the transaction is one
    ! initiated by this process, and not a previous incomplete transaction,
    ! TRANSACTION_IN_PROGRESS is also tested.
    !-

    ! The following is an optimized version of a simple AND .
    if not .transaction_in_progress then false else
		isfile(len_comma_ptr(%string(lib, bad)), k_null)

    end ;	! NOWTRN
GLOBAL ROUTINE numtrn =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine retruns the number of completed transactions. The
!	counter, NUMBER_OF_TRANSACTIONS , is incremented by one at the
!	end of the routine ENDTRN.	
!
! FORMAL PARAMETERS:
!
!	none
!
! IMPLICIT INPUTS:
!
!	The variable NUMBER_OF_TRANSACTIONS declared OWN in this module.
!
! IMPLICIT OUTPUTS:
!
!	none
!
! ROUTINE VALUE and
! COMPLETION CODES:
!
!	The value of NUMBER_OF_TRANSACTIONS.
!
! SIDE EFFECTS:
!
!	none
!
!--

    BEGIN			! NUMTRN

    .number_of_transactions 

    END;			! NUMTRN
global routine oldtrn =

!++
! Functional Description:
!
!	This routine returns TRUE if and only if the previous transaction
!	was incomplete.  It may be called only if a new transaction is
!	not currently being made, i.e., only if any calls to BEGTRN have
!	been matched by corresponding calls to ENDTRN or CANTRN.
!
! Formal Parameters:
!
!	None
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	See functional description.
!
! Side Effects:
!
!	None
!
!--

    begin	! OLDTRN
    local
	incomplete,		! The previous transaction did not finish.
	need_to_release ;	! The library was seized by this routine.

    ! Initialize.
    need_to_release = false ;

    ! Cannot detect a prior transaction if a new one has started.
    if .transaction_in_progress
    then
	bug(lit('OLDTRN called during a new transaction')) ;

    ! If this process is not using the library but another user is, there
    ! is no way of detecting that a previous transaction is incomplete.
    if not librea()
    then
	begin	! Current process is not using the library.
	local
	    dummy ;		! Second argument to TRYLIB is not used.

	! Assume there is no incomplete transaction if the library is
	! in use by someone else.
	if not trylib(k_verify_lib, dummy) ! K_VERIFY_LIB avoids a recursive
					   ! call to OLDTRN .
	then
	    return false ;

	need_to_release = true ;
	end ;	! Current process is not using the library.

    ! The library is now secure for the current process.  If 00fac_name.BAD is
    ! present, the previous transaction is incomplete.
    incomplete = isfile(len_comma_ptr(%string(lib,bad)), k_null) ;

    ! Release the library if it was seized by this routine.
    if .need_to_release
    then
	donlib() ;

    .incomplete

    end ;	! OLDTRN
global routine trnfil(a_iob) : novalue =

!++
! Functional Description:
!
!	This routine sets the proper protection code for a library file, and
!	sets other characteristics needed for the file to be part of a
!	recoverable transaction.  The file must be open.
!
!	The protection code is set according to the functional requirements
!	of the file (e.g., the log file is given append access), and according
!	to the requirements of the recovery mechanism.
!
!	The other characteristics set are the revision time, and a host-
!	dependent indication so that after the file is closed it can be
!	recognized as having been closed by STEP.  The revision time is the
!	official time for this transaction as established by BEGTRN.
!
!	The protection code and other characteristics are set only if the file
!	is being created, because this process might not be able to change the
!	header of an existing file.
!
!	If this routine is called for a file opened for OVERWRITE or APPEND,
!	and the file is being created, the most recent XPORT operation for the
!	IOB must have been the OPEN.  This is an implementation restriction
!	that is harmless in the current design of STEP.
!	
!	This routine must not be called before BEGTRN, nor after ENDTRN or
!	CANTRN, unless BEGTRN is first called again.
!
!	Before ENDTRN or CANTRN is called, each IOB for which this routine is
!	called must be closed without the REMEMBER option.  This rule does not
!	apply to BAD_IOB, which is declared OWN in this module.
!
! Formal Parameters:
!
!	a_iob:		Address of the IOB for an open file whose
!			characteristics are to be set.  Host-dependent
!			control blocks allocated in TRNZON will be attached
!			to the IOB.
!
! Implicit Inputs:
!
!	The zone block TRNZON declared OWN in this module.
!	The time block TRANSACTION_TIME declared OWN in this module.
!
! Implicit Outputs:
!
!	The variable LOG_FILE_SET declared OWN in this module.
!	The zone block TRNZON declared OWN in this module.
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	System dependent control blocks attached to the IOB are allocated in
!	TRNZON.  Since TRNZON will be flushed by ENDTRN or CANTRN, all the
!	IOB's for which TRNFIL is called must be closed without the REMEMBER
!	option before ENDTRN or CANTRN is called.  (This rule does not apply to
!	BAD_IOB, declared OWN in this module, because its file is closed
!	without the REMEMBER option by ENDTRN or CANTRN itself before TRNZON
!	is flushed.)
!
!--

    begin	! TRNFIL
    bind
	iob = .a_iob : $xpo_iob() ;
    local
	dir_spec : desc_block,			! Directory part of file spec.
	is_error_log,				! Means the file is the
						! library's error log.
	is_library,				! Means the file's directory
						! is the library.
	group_access : access_fullword,		! Access codes for the group.
	owner_access : access_fullword,		! Access codes for the owner.
	world_access : access_fullword ;	! Access codes for the world.

    ! Check the sequencing of calls.
    if not .transaction_in_progress
    then
	bug(lit('TRNFIL called before BEGTRN')) ;

    ! Make sure the file is properly open.
    if not
	(.iob[iob$v_open] and .iob[iob$v_output] and not .iob[iob$v_terminal])
    then
	bugiob(iob, lit('TRNFIL called with an invalid IOB')) ;

    ! Make sure the file is a library file.
    dirspc(iob[iob$t_resultant], dir_spec) ;
    if not isdir(len_comma_ptr(dir_spec), k_null, k_null)
    then
	bugiob(iob, lit('TRNFIL did not find a directory')) ;

    ! Compute the standard access code needed for most library files.
%if %bliss(bliss32) %then
    owner_access =		! Standard access for all files.
		k_r_access or	! Functional requirement.
		k_a_access or	! Needed to append checksum record (VER/REPAIR)
		k_d_access ;	! Needed for recovery and cleanup.
%fi
%if %bliss(bliss36) %then
    %if %switches(tops20) %then
    owner_access =		! Standard access for all files.
		k_r_access or	! Functional requirement.
                k_l_access or   ! Needed for TOPS20
		k_a_access or	! Needed to append checksum record (VER/REPAIR)
		k_d_access ;	! Needed for recovery and cleanup.
    %else
    %error('DS-10 support not implemented')
    %fi
%fi
    ! Note if this is the log file, and augment the access code accordingly.
    if nateql(iob[iob$t_resultant], lit(%string(lib,log)))
    then
	begin	! Log file.
	log_file_set = true ;
%if %bliss(bliss32) %then
	owner_access = .owner_access or	! Additional access for log file.
			k_a_access or	! Functional requirement.
			k_w_access ;	! May be needed for recovery.
%fi
%if %bliss(bliss36) %then
    %if %switches(tops20) %then
	owner_access = .owner_access or	! Additional access for log file.
			k_a_access or	! Functional requirement.
                        k_l_access or   ! Needed for TOPS20
			k_w_access ;	! May be needed for recovery.
    %else
        %error('DS-10 support not implemented')
    %fi
%fi
    
	end ;	! Log file.

    ! Note if this is the error logging file, and augment the access code
    ! accordingly.  TRNFIL should be called for the error logging
    ! file only when the library is being initialized.
    if nateql(iob[iob$t_resultant], lit(%string(lib,erlg)))
    then
	begin	! Error logging file.
	if not libini()
	then
	    bug(lit('TRNFIL was wrongly called for the error logging file')) ;
	is_error_log = true ;
	owner_access = .owner_access or	! Additional access for error log.
			k_a_access ;	! Functional requirement.
	end	! Error logging file.
    else
	is_error_log = false ;

    ! Extend the access to the group or world as required.
    group_access = (if .group_library then .owner_access else 0) ;
    world_access = (if .world_library then .owner_access else 0) ;

    !+
    ! Set the protection codes and revision information to be established on
    ! close, but only if the file is being created.  (If the file is not being
    ! created, this process might not be its owner, and so might not be able
    ! to set the file's header information.)
    !
    ! The method used here to detect whether a file is being created is not
    ! completely accurate, but is adequate for the current design of STEP.
    ! If a file is opened for ouput only (without the overwrite or append
    ! options) it is always created, and so its protection is always set.
    ! For an overwrite or append file that is being created, the protection
    ! will be set only if the most recent XPORT operation on the IOB was OPEN.
    !-
    if (not .iob[iob$v_overwrite] and not .iob[iob$v_append])
	or .iob[iob$g_comp_code] eql step$_created
    then
	begin	! Set file header.

	! Set the protection codes.
	protec(iob, trnzon, .owner_access, .group_access, .world_access) ;

	! Make the revision time be the official transaction time, and set a
	! mark by which to recognize that we closed the file.
	mrkrev(iob, trnzon, transaction_time) ;

	end ;	! Set file header.

    end ;	! TRNFIL
global routine trntim(a_time) : novalue =

!++
! Functional Description:
!
!	This routine gets the official time of the current transaction, as
!	established by BEGTRN.  It must not be called unless a transaction
!	is being made, i.e., it must be called after BEGTRN but before the
!	corresponding call to ENDTRN or CANTRN.
!
! Formal Parameters:
!
!	a_time:		Address of a time block to receive the official
!			transaction time in system format.
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	None
!
! Side Effects:
!
!	None
!
!--

    begin	! TRNTIM
    bind
	time = .a_time : time_block ;

    ! Make sure the call is legal.
    if not .transaction_in_progress
    then
	bug(lit('TRNTIM called outside a transaction')) ;

    timcop(transaction_time, time) ;
    end ;	! TRNTIM
end				! Module TRANSA
eludom