home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c004 / 4.ddi / WATCOM / CTCLIB.C next >
Encoding:
C/C++ Source or Header  |  1989-04-18  |  7.9 KB  |  326 lines

  1. /*
  2.  *    CTCLIB.C module for WATCOMC
  3.  *
  4.  *    Due to the highly restrictive nature of the DOS 3.1 locking protocols
  5.  *    (i.e., you cannot READ a region of a file locked by another process),
  6.  *    we have provided a work-around which requires a dummy file as file
  7.  *    number zero. In particular, the zeroth data file of each ISAM parameter
  8.  *    file should be a dummy file, have a record length of 128 bytes, 
  9.  *     and file mode parameters indicating a SHARED, PERMANENT, FIXED length 
  10.  *    file. Then, instead of actually locking the files in use, c-tree will
  11.  *    place ct_locks on corresponding regions of the dummy file.
  12.  *
  13.  *    Due to the use of a dummy lock file, it is not necessary for the
  14.  *    lock routines to increment and decrement the lokcnt member which
  15.  *    is used for checking virtual files.
  16.  *
  17.  *    (MS-DOS is a trademark of Microsoft)
  18.  *
  19.  *    This program is the CONFIDENTIAL and PROPRIETARY property 
  20.  *    of FairCom(R) Corporation. Any unauthorized use, reproduction or
  21.  *    transfer of this program is strictly prohibited.
  22.  *
  23.  *      Copyright (c) 1985, 1986, 1987, 1988, 1989 FairCom
  24.  *    (Subject to limited distribution and
  25.  *     restricted disclosure only.)
  26.  *    *** ALL RIGHTS RESERVED ***
  27.  *
  28.  *    4006 West Broadway
  29.  *    Columbia, MO 65203
  30.  *
  31.  *
  32.  *    c-tree(R)    Version 4.3
  33.  *            Release C
  34.  *            February 7, 1989 17:30
  35.  *
  36.  */
  37.  
  38. #include "ctstdr.h"        /* standard i/o header         */
  39. #undef   EXTERN
  40. #define  EXTERN /* */
  41. #include "ctoptn.h"        /* c-tree configuration options */
  42. #include "cterrc.h"        /* c-tree error codes        */
  43. #include "ctstrc.h"        /* c-tree data structures    */
  44. #include "ctgvar.h"        /* c-tree global variables    */
  45.  
  46. #include <sys\types.h>
  47. #include <share.h>
  48. #include <sys\stat.h>
  49.  
  50. #define    INFINITY    3000    /* loop termination count waiting for lock */
  51. #define LEFT_SHIFT    24    /* controls dummy lock capacity */
  52.                 /* 25 => 62  files: 32M fixed records or */
  53.                 /*            32MB var len file    */
  54.                 /* 24 => 126 files: 16M fixed records or */
  55.                 /*            16MB var len file    */
  56.                 /* 23 => 254 files:  8M fixed records or */
  57.                 /*             8MB var len file    */
  58.                 /* 22 => 510 files:  4M fixed records or */
  59.                 /*             4MB var len file    */
  60.  
  61. COUNT ctseek(),uerr();
  62.  
  63. RNDFILE mbopen(ctnum,opmode)
  64. PFAST CTFILE  *ctnum;
  65. COUNT             opmode;    /* EXCLUSIVE or SHARED */
  66. {
  67.     RNDFILE retval;
  68.     int     acflag,shflag,pmflag;
  69.  
  70.     COUNT vtclose();
  71.  
  72.     ctnum->sekpos = DRNZERO;
  73.     acflag          = BUPDATE;
  74.     pmflag          = (S_IWRITE | S_IREAD);
  75. #ifdef FPUTFGET
  76.     if (opmode & SHARED)
  77.         shflag = SH_DENYNO;
  78.     else if (opmode & READFIL) {
  79.         shflag = SH_DENYWR;
  80.         acflag = (O_BINARY | O_RDONLY);
  81.         pmflag = S_IREAD;
  82.     } else
  83.         shflag = SH_DENYRW;
  84. #else
  85.     shflag = SH_DENYRW;
  86.     if (opmode & READFIL) {
  87.         acflag = (O_BINARY | O_RDONLY);
  88.         pmflag = S_IREAD;
  89.     }
  90. #endif
  91.  
  92.     if (!(opmode & PERMANENT) && ct_numvfil >= MAXVFIL)
  93.         vtclose();
  94.  
  95.     if ((retval = sopen(ctnum->flname,acflag,shflag,pmflag)) < 0)
  96.         if (vtclose() == YES)
  97.             retval = sopen(ctnum->flname,acflag,shflag,pmflag);
  98.  
  99.     if (!(opmode & PERMANENT) && retval >= 0)
  100.         ct_numvfil++;
  101.  
  102.     return(retval);
  103. }
  104.  
  105. /* ------------------------------------------------------------ */
  106.  
  107. RNDFILE mbcrat(ctnum)
  108. PFAST CTFILE  *ctnum;
  109. {
  110.     RNDFILE retval;
  111.  
  112.     COUNT vtclose();
  113.  
  114.     ctnum->sekpos = DRNZERO;
  115.     if (!(ctnum->flmode & PERMANENT) && ct_numvfil >= MAXVFIL)
  116.         vtclose();
  117.  
  118.     if ((retval = open(ctnum->flname,
  119.         BCREATE,(S_IREAD | S_IWRITE))) < 0)
  120.         if (vtclose() == YES)
  121.             retval = open(ctnum->flname,
  122.                 BCREATE,
  123.                 (S_IREAD | S_IWRITE));
  124.  
  125.     if (!(ctnum->flmode & PERMANENT) && retval >= 0)
  126.         ct_numvfil++;
  127.  
  128.     return(retval);
  129. }
  130.  
  131. /* ------------------------------------------------------------ */
  132.  
  133. COUNT mbsave( ctnum)
  134. PFAST CTFILE *ctnum;
  135. {
  136.     COUNT   mbclos();
  137.     RNDFILE mbopen();
  138.  
  139.     if (mbclos(ctnum,ctnum->flmode))
  140.         return(uerr(FSAV_ERR));
  141.     else if ((ctnum->fd = mbopen(ctnum,ctnum->flmode)) < 0)
  142.         return(uerr(FSAV_ERR));
  143.     else
  144.         return(NO_ERROR);
  145. }
  146.  
  147. VOID flushdos(datno)
  148. COUNT         datno;
  149. {
  150.     bdos(13,0,0);
  151. }
  152.  
  153. #ifndef CTSERVER
  154.  
  155. /* --------------------------------------------------------------------
  156.    LOCK index node
  157.  */
  158.  
  159. COUNT LOCK(node,knum)    /* node == 0  => header */
  160. LONG       node;
  161. PFAST KEYFILE  *knum;
  162. {
  163.  
  164. /*
  165.  * c-tree node locking protocol is guaranteed to be deadlock free. Therefore,
  166.  * if a lock is unsucessful, this routine forces a short delay and then 
  167.  * attempts the lock again.  The INFINITY parameter allows one to avoid
  168.  * an infinite loop if there is a bug in the lock routines.  Theoretically,
  169.  * the while loop should never run indefinitely.
  170.  */
  171.  
  172.  
  173. #ifdef FPUTFGET
  174.  
  175.     COUNT dummy,tries;
  176.  
  177.     tries = 0;
  178.     knum -= knum->kmem;
  179.     if (!(knum->flmode & NONEXCLUSIVE))
  180.         return(NO_ERROR);
  181.  
  182. /*
  183.  * Notice how a lock region is converted to a phantom region of the dummy
  184.  * file and the lock is applied to file zero (whose control structure is
  185.  * pointed to by the global variable ct_key).
  186.  */
  187.     if (knum->clstyp != VAT_CLOSE)
  188.         node /= knum->recsiz;
  189.     node |= ((LONG) knum->filnum << LEFT_SHIFT);
  190.     if (ctseek(ct_key,node))
  191.         return(uerr(SEEK_ERR));
  192.     while (locking(ct_key->fd,LK_NBLCK,1L))
  193.         if (tries++ > INFINITY)
  194.             return(uerr(LNOD_ERR));
  195.         else
  196.             /* delay and try again */
  197.             for (dummy = 0; dummy++ < INFINITY; )
  198.                 ;
  199.     return(NO_ERROR);
  200. #else
  201.     return(NO_ERROR);
  202. #endif
  203.  
  204. }
  205.  
  206. /* --------------------------------------------------------------------
  207.    UNLOCK index file node
  208. */
  209.  
  210. COUNT UNLOCK(node,knum)
  211. LONG         node;
  212. PFAST KEYFILE    *knum;
  213. {
  214.  
  215. #ifdef FPUTFGET
  216.     knum -= knum->kmem;
  217.     if (!(knum->flmode & NONEXCLUSIVE))
  218.         return(NO_ERROR);
  219.  
  220.     if (knum->clstyp != VAT_CLOSE)
  221.         node /= knum->recsiz;
  222.     node |= ((LONG) knum->filnum << LEFT_SHIFT);
  223.     if (ctseek(ct_key,node))
  224.         return(uerr(SEEK_ERR));
  225.     else if (locking(ct_key->fd,LK_UNLCK,1L))
  226.         return(uerr(UNOD_ERR));
  227.     else
  228.         return(NO_ERROR);
  229. #else
  230.     return(NO_ERROR);
  231. #endif
  232.  
  233. }
  234.  
  235.  
  236. /* --------------------------------------------------------------------
  237.    LOCK data record
  238.  */
  239.  
  240. COUNT DLOCK(recbyt,dnum)        /* recbyt == 0  => header record */
  241. POINTER        recbyt;
  242. PFAST DATFILE      *dnum;
  243. {
  244.  
  245. /*
  246.  * the data record locks are NOT guaranteed to be deadlock free.  Therefore,
  247.  * except for the header record which is only locked by internal c-tree 
  248.  * maintenance requests, the data record lock routine returns instead of
  249.  * looping when a lock is denied because of a competing lock.  The application
  250.  * program must deal with the appropriate action if a lock is denied to a
  251.  * data record.
  252.  */
  253.  
  254. #ifdef FPUTFGET
  255.     COUNT dummy,tries,test;
  256.     LONG  actbyt;
  257.  
  258.     if (!(dnum->flmode & NONEXCLUSIVE))
  259.         return(NO_ERROR);
  260.  
  261.     actbyt  = recbyt;
  262.     tries   = 0;
  263.     if (dnum->clstyp != VAT_CLOSE)
  264.         recbyt /= dnum->reclen;
  265.     recbyt |= ((LONG) dnum->filnum << LEFT_SHIFT);
  266.     if (ctseek(ct_key,recbyt))
  267.         return(uerr(SEEK_ERR));
  268.     while ((test = locking(ct_key->fd,LK_NBLCK,1L)) &&
  269.         actbyt == DRNZERO) /* i.e., the header record is locked */ 
  270.         if (tries++ > INFINITY)
  271.             return(uerr(DLOK_ERR));
  272.         else
  273.             /* delay and try again */
  274.             for (dummy = 0; dummy++ < INFINITY; )
  275.                 ;
  276.  
  277.     if (!test)            /* lock request is successful!  */
  278.         return(NO_ERROR);
  279.     else 
  280.         return(uerr(DLOK_ERR));
  281. #else
  282.     return(NO_ERROR);
  283. #endif
  284.  
  285. }
  286.  
  287. COUNT RLOCK(recbyt,dnum)
  288. POINTER        recbyt;
  289. PFAST DATFILE      *dnum;
  290. {
  291.     return(NO_ERROR); /* read locks not supported */
  292. }
  293.  
  294. /* --------------------------------------------------------------------
  295.    UNLOCK data record
  296. */
  297.  
  298. COUNT UDLOCK(recbyt,dnum)
  299. POINTER         recbyt;
  300. PFAST DATFILE       *dnum;
  301. {
  302.  
  303. #ifdef FPUTFGET
  304.     if (!(dnum->flmode & NONEXCLUSIVE))
  305.         return(NO_ERROR);
  306.  
  307.     if (dnum->clstyp != VAT_CLOSE)
  308.         recbyt /= dnum->reclen;
  309.     recbyt |= ((LONG) dnum->filnum << LEFT_SHIFT);
  310.     if (ctseek(ct_key,recbyt))
  311.         return(uerr(SEEK_ERR));
  312.     if (locking(ct_key->fd,LK_UNLCK,1L))
  313.         return(uerr(UDLK_ERR));
  314.     else
  315.         return(NO_ERROR);
  316.  
  317. #else
  318.     return(NO_ERROR);
  319. #endif
  320.  
  321. }
  322.  
  323. #endif
  324.  
  325. /* end of ctclib.msc */
  326.