                                                August 1999
Files modified to implement file locking.

file                    comment
------------------------------------------------------------------

flock/locking           documentation
misc/magic.h            added #define FILE_LOCKS
database/database.h     define CDNOEDIT cd_flag and flock_list
database/DBio.c         definition of locking functions, and I/O calls.
                        fixed :save command error
database/DBcellname.c   diagnostics
dbwind/DBWprocs.c       apply CDNOEDIT tests
commands/cmde.c         checks on :edit command 
commands/cmdlq.c        lock on :open command
windows/windclient.c    defn: flock_close_wlist()
windows/windcmdam.c     call to flock_close_wlist on window close
windows/windcmdnr.c     Diagnostic code in windOpenCmd
main/main.c             call to flock_close_wlist on Magic exit.
utils/path.c            control of fopens

The logic of the file locking implementation is as follows:

First, Magic checks if there is a directory named flock in the directory
given by CAD_ROOT. If directory flock is not present Magic turns off
flie locking. If file locking is on:

1. When a file is opened due to being named on the call line, or used in
   a :load or :open command its status is checked.

   If it is not locked, lock is set and file is opened r/w (if permissions
   allow).

   If it is locked, the file is opened read-only and NOT editing cell. An
   attempt to use :edit to make it the editing cell will be rejected.

2. A list of locked files is maintained in each magic execution.
   Magic does (more or less)
   open/close sequences when reading/writing files. In addition, Magic
   just exits when it is :quit. The conditions that can cause the locking to
   release a lock are :close and :quit. In principle some cell's locks
   could be released on :close. However, if a window contains a root
   cell which contains references to other cells down the hierarchy, only
   the cells which are the root or have been expanded will have been
   read from the filesystem and locked. Cells that are unexpanded are
   not written back nor unlocked. The same cell may appear in multiple
   windows in a locked or unlocked state. This all leads to the choice
   that :close does not unlock any files. On :quit all locks are released.

3. When Magic starts, a lock directory (flock_list) is created in the current
   directory. A file is written in this directory for each local *.mag file
   read by Magic. The file name is the lock record. This record is removed
   on normal (:quit) termination. When Magic starts it checks for any
   "leftover" locks and tries to clear any "stale" ones. Files that are read
   from other directories (by being found through library paths or directly)
   are unconditionally marked as read-only. Normally such files should not
   be updated. If they are to be updated Magic must be executed from the
   directory containing the file.

   The following may be implemented to reduce problems due to "stale locks"
   leftover from cases such as magic crashes: During execution Magic
   updates the timestamp of its lock once every 10s. locks older
   than 10s are stale. Ideally, a simple thread would do this, but...

                         UPDATE HISTORY
   -------------------------------------------------------------------

   5 January 2000: It was discovered that the use of :addpath and,
   generally, reading files from other directories had not been considered
   properly. In fact, use of :addpath led to a magic crash since it tried
   to create an invalid filename. This has now been corrected as 
   described above. All non-local files are are marked read-only.


