Clipper Support Bulletin #8
Solutions for Open Error (4)

Copyright (c) 1992 Nantucket Corporation.  All rights reserved.


Version:  Clipper 5.0, version 5.01
Date:     2nd January, 1992
Revised:  22nd May, 1992
Status:   Active

================================================================================

This Support Bulletin covers the following topics:

   1. Problems and solutions
   2. Additional notes

================================================================================
1. Problems and solutions
   
   Open Error (4) means that not enough file handles were available
   for the operation being performed.  The following are some things
   to try in order to eliminate the problem:
   
   1. Check the version of DOS you're using.  Versions of DOS lower
      than 3.3 allow a maximum of 20 file handles.  This figure can
      be increased by using a utility such as HANDLES.OBJ, which can
      be found on NANFORUM on CompuServe.
      
   2. Check the setting of the FILES parameter in your CONFIG.SYS
      file, and increase it if necessary.
      
   3. Check the setting of the F parameter in your CLIPPER
      environment variable.  This should be the same as the setting
      of the FILES parameter in your CONFIG.SYS file.  If you are
      using DOS 3.3, the F parameter should be set to an odd number.
      Due to an anomaly in this version of the operating system, 64K
      of memory is wasted if an even number is used (see PC Tech
      Journal, April 1988, Page 162).
      
   4. If you're in a network environment, increase the number of file
      handles allocated to the workstation experiencing the error.
      
   5. If you're using DOS 4.x, the problem may be that the /F
      parameter of the SHARE command is not set to a large enough
      figure.  Try increasing it as follows: SHARE /F:10000 (bytes)
      
================================================================================
2. Additional notes
   
   If the file server on a Novell network uses all its available file
   handles, requesting another handle will result in an Open Error
   (5) rather than Open Error (4).  If you experience an Open Error
   (5) and think this may be the cause, look at the statistics area
   of FCONSOLE.  You will see the maximum number of handles allowed,
   the maximum currently open, and most importantly, the maximum ever
   reached.
   
   The Virtual Memory Manager will use one file handle if it needs to
   write information to disk.  The Dynamic Overlay Manager uses two
   handles by default, and if static overlays are present, the Static
   Overlay Manager uses one handle.  If you're experiencing an Open
   Error (4), be sure to include these allocations when calculating
   the number of file handles your application is using.
   
   If you have insufficient control over your users' environments to
   stipulate the setting of the FILES parameter in CONFIG.SYS, you
   may need to check the number of file handles available before
   opening a file.  This can be achieved by use of the following
   code:
   
   /***
   * Handles( nToCheck ) --> number of handles opened
   * Function to check the number of file handles used
   *
   * Copyright (c) 1990-1992 Nantucket Corp.  All rights reserved.
   * Scott McIntosh
   *
   * NOTE: Compile with /N /W /A
   *
   * If a number is passed, this function tests to see if that
   *   number of files can be opened.
   * If no number is passed, the function returns the maximum
   *   number of files that can be opened.
   */
   FUNCTION Handles( nToCheck )
     LOCAL nOpened, nClosed, nHandle, aHandles := {}
   
     // If no parameter is passed, try to open all 250 handles
     nToCheck := IF( nToCheck == NIL, 250, nToCheck )
     FOR nOpened := 1 TO nToCheck
   
       // Open the NUL device--it only fails if there is no handle
   nHandle := FOPEN("NUL")
   
       // If nHandle is -1, FOPEN() failed
       IF nHandle == -1
            EXIT
       ENDIF
   
       // Store handles in an array so we can close them later
       AADD( aHandles, nHandle )
   
     NEXT
   
     // nOpened has already incremented, so decrement it nOpened--
     FOR nClosed := 1 TO nOpened
   
       FCLOSE( aHandles[nClosed] )
     NEXT
   
     RETURN (nOpened)
   
   
   // Sample usage of Handles function:
   PROCEDURE Test
     CLS
     ? Handles()       // Total number of file handles available
   
     // Can we open 15 handles? (faster than opening ALL handles)
     IF (Handles( 15 ) == 15)
       ? "We have at least 15 file handles left..."
     ENDIF
     RETURN
   

                              *  *  *
