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

  1. /*
  2.  *    XENIX V CTCLIB.C module
  3.  *
  4.  *    Due to a bug in the non-exclusive record locks in System V Release 2.0
  5.  *    (RLCK & NBRLCK which are described as the same as exclusive locks,
  6.  *    but reads are permitted; and in fact allow more than one process
  7.  *    to own the lock and allow an owner to update the record when there
  8.  *    are no other owners - hence they are neither write locks nor read
  9.  *    locks), we have provided two locking modes:
  10.  *
  11.  *        1) REGULAR - for use when advisory/exclusive locks are
  12.  *                 available; and
  13.  *        2) PHANTOM - otherwise.
  14.  *
  15.  *    c-tree does not require exclusive locks (which deny both read and
  16.  *    write permission to other processes), but does want write locks: only
  17.  *    one process can lock the record, but other processes may read the
  18.  *    record.
  19.  *
  20.  *    Use REGULAR (by commenting out the #define PHANTOM) when exclusive
  21.  *    are available in the adivory mode (i.e., a process can read the locked
  22.  *    region if it does not ask for a lock which is how c-tree is designed.)
  23.  *
  24.  *    In the PHANTOM mode, exclusive locks are place on a dummy file so 
  25.  *    that all processes can still read locked regions of the real files.
  26.  *    In particular, the zeroth data file of each ISAM parameter
  27.  *    file should be a dummy file, have a record length of 128 bytes, 
  28.  *     and file mode parameters indicating a SHARED, PERMANENT, FIXED length 
  29.  *    file. Then, instead of actually locking the files in use, c-tree will
  30.  *    place locks on corresponding regions of the dummy file. 
  31.  *
  32.  *    This program is the CONFIDENTIAL and PROPRIETARY property 
  33.  *    of FairCom(R) Corporation. Any unauthorized use, reproduction or
  34.  *    transfer of this program is strictly prohibited.
  35.  *
  36.  *      Copyright (c) 1985, 1986, 1987, 1988, 1989 FairCom
  37.  *    (Subject to limited distribution and
  38.  *     restricted disclosure only.)
  39.  *    *** ALL RIGHTS RESERVED ***
  40.  *
  41.  *    4006 West Broadway
  42.  *    Columbia, MO 65203
  43.  *
  44.  *
  45.  *    c-tree(R)    Version 4.3
  46.  *            Release C
  47.  *            February 7, 1989 17:30
  48.  *
  49.  */
  50.  
  51. #include "ctstdr.h"        /* standard i/o header         */
  52. #undef   EXTERN
  53. #define  EXTERN /* */
  54. #include "ctoptn.h"        /* c-tree configuration options */
  55. #include "cterrc.h"        /* c-tree error codes        */
  56. #include "ctstrc.h"        /* c-tree data structures    */
  57. #include "ctgvar.h"        /* c-tree global variables    */
  58. #include <sys/types.h>
  59. #include <sys/locking.h>
  60.  
  61. #define PHANTOM       /* delete when exclusive/advisory locks are available */
  62.  
  63. #ifdef  PHANTOM
  64. #define LEFT_SHIFT    24    /* controls dummy lock capacity */
  65.                 /* 25 => 62  files: 32M fixed records or */
  66.                 /*            32MB var len file    */
  67.                 /* 24 => 126 files: 16M fixed records or */
  68.                 /*            16MB var len file    */
  69.                 /* 23 => 254 files:  8M fixed records or */
  70.                 /*             8MB var len file    */
  71.                 /* 22 => 510 files:  4M fixed records or */
  72.                 /*             4MB var len file    */
  73. #endif
  74.  
  75. COUNT ctseek(),uerr();
  76.    
  77. RNDFILE mbopen(ctnum,opmode)
  78. PFAST CTFILE *ctnum;
  79. COUNT opmode;
  80. {
  81.     RNDFILE retval;
  82.     int    acflag;
  83. #ifndef CTSERVER
  84.     int    i;
  85.     long lseek();
  86. #endif
  87.  
  88.     COUNT vtclose();
  89.  
  90.     ctnum->sekpos = 0L;
  91.     acflag          = BUPDATE;
  92.     if (opmode & READFIL)
  93.         acflag = O_RDONLY;
  94.  
  95.     if (!(opmode & PERMANENT) && ct_numvfil >= MAXVFIL)
  96.         vtclose();
  97.  
  98.     if ((retval = open(ctnum->flname,acflag)) < 0)
  99.         if (vtclose() == YES)
  100.             retval = open(ctnum->flname,acflag);
  101.  
  102. #ifdef CTSERVER
  103.     if (retval > -1 && locking(retval,LK_NBLCK,0L)) {
  104.         close(retval);
  105.         return(-1);
  106.     }
  107. #else
  108.     /* obtain lock on entire file if exclusive open */
  109.     if (retval > -1 && !(opmode & NONEXCLUSIVE)) {
  110.         lseek(retval,ctnum->sekpos = HDRSIZ,0);
  111.         if (locking(retval,LK_NBLCK,0L)) {
  112.             close(retval);
  113.             return(-1);
  114.         }
  115.     } else if (retval > -1 && (opmode & NONEXCLUSIVE)) {
  116.         /* check file type to see if index: no lock on index */
  117.         if (read(retval,ctnum,HDRSIZ) != HDRSIZ) {
  118.             close(retval);
  119.             return(-1);
  120.         } else {
  121. #ifdef UNIFRMAT
  122.             revhdr(ctnum);
  123. #endif
  124.             ctnum->sekpos = HDRSIZ;
  125.         }
  126.         if (ctnum->clstyp != IDX_CLOSE) {
  127.             for (i = HDRSIZ; i < 128; i++) {
  128.                 lseek(retval,ctnum->sekpos = i,0);
  129.                 if (locking(retval,LK_NBLCK,1L) == 0)
  130.                     break;
  131.             }
  132.             if (i >= 128) {
  133.                 close(retval);
  134.                 return(-1);
  135.             }
  136.         }
  137.     }
  138. #endif
  139.  
  140.     if (!(opmode & PERMANENT) && retval >= 0)
  141.         ct_numvfil++;
  142.  
  143.     return(retval);
  144. }
  145.  
  146. /* ------------------------------------------------------------ */
  147.  
  148. RNDFILE mbcrat(ctnum)
  149. PFAST CTFILE *ctnum;
  150. {
  151.     RNDFILE retval;
  152.  
  153.     COUNT vtclose();
  154.  
  155.     ctnum->sekpos = 0L;
  156.     if (!(ctnum->flmode & PERMANENT) && ct_numvfil >= MAXVFIL)
  157.         vtclose();
  158.  
  159.     if ((retval = creat(ctnum->flname,BCREATE)) < 0)
  160.         if (vtclose() == YES)
  161.             retval = creat(ctnum->flname,BCREATE);
  162.  
  163.     if (!(ctnum->flmode & PERMANENT) && retval >= 0)
  164.         ct_numvfil++;
  165.  
  166.     return(retval);
  167. }
  168.  
  169. /* ------------------------------------------------------------ */
  170.  
  171. COUNT mbsave(ctnum)
  172. PFAST CTFILE *ctnum;
  173. {
  174.     sync();
  175.     return(NO_ERROR);
  176. }
  177.  
  178. VOID flushdos(datno)
  179. COUNT          datno;
  180. {
  181.     sync();
  182. }
  183.  
  184. #ifndef CTSERVER
  185.  
  186. /* --------------------------------------------------------------------
  187.    LOCK index node
  188.  */
  189.  
  190. COUNT LOCK(node,knum)    /* node == 0  => header */
  191. LONG node;
  192. PFAST KEYFILE *knum;
  193. {
  194.  
  195. /*
  196.  * c-tree node locking protocol is guaranteed to be deadlock free. Therefore,
  197.  * the lock request allows the process to "sleep" if the lock is not
  198.  * immediately available.
  199.  */
  200.  
  201. #ifdef FPUTFGET
  202. #ifndef PHANTOM
  203.     knum -= knum->kmem;
  204.     if (!(knum->flmode & NONEXCLUSIVE))
  205.         return(NO_ERROR);
  206.  
  207.     if (ctseek(knum,node))
  208.         return(uerr(SEEK_ERR));
  209.     if (locking(knum->fd,LK_LOCK,1L))
  210.         return(uerr(LNOD_ERR));
  211.     else {
  212.         knum->lokcnt++;
  213.         return(NO_ERROR);
  214.     }
  215. #else
  216.     knum -= knum->kmem;
  217.     if (!(knum->flmode & NONEXCLUSIVE))
  218.         return(NO_ERROR);
  219.  
  220. /*
  221.  * Notice how a lock region is converted to a phantom region of the dummy
  222.  * file and the lock is applied to file zero (whose control structure is
  223.  * pointed to by the global variable key).
  224.  */
  225.     if (knum->clstyp != VAT_CLOSE)
  226.         node /= knum->recsiz;
  227.     node |= ((LONG) knum->filnum << LEFT_SHIFT);
  228.     if (ctseek(ct_key,node))
  229.         return(uerr(SEEK_ERR));
  230.     if (locking(ct_key->fd,LK_LOCK,1L))
  231.         return(uerr(LNOD_ERR));
  232.     else {
  233.         knum->lokcnt++;
  234.         return(NO_ERROR);
  235.     }
  236. #endif
  237. #else
  238.     return(NO_ERROR);
  239. #endif
  240.  
  241. }
  242.  
  243. /* --------------------------------------------------------------------
  244.    UNLOCK index file node
  245. */
  246.  
  247. COUNT UNLOCK(node,knum)
  248. LONG node;
  249. PFAST KEYFILE *knum;
  250. {
  251.  
  252. #ifdef FPUTFGET
  253.     knum -= knum->kmem;
  254.     if (!(knum->flmode & NONEXCLUSIVE))
  255.         return(NO_ERROR);
  256.  
  257.     if (knum->lokcnt)
  258.         knum->lokcnt--;
  259. #ifndef PHANTOM
  260.     if (ctseek(knum,node))
  261.         return(uerr(SEEK_ERR));
  262.     if (locking(knum->fd,LK_UNLCK,1L))
  263.         return(uerr(UNOD_ERR));
  264. #else
  265.     if (knum->clstyp != VAT_CLOSE)
  266.         node /= knum->recsiz;
  267.     node |= ((LONG) knum->filnum << LEFT_SHIFT);
  268.     if (ctseek(ct_key,node))
  269.         return(uerr(SEEK_ERR));
  270.     if (locking(ct_key->fd,LK_UNLCK,1L))
  271.         return(uerr(UNOD_ERR));
  272. #endif
  273.     return(NO_ERROR);
  274. #else
  275.     return(NO_ERROR);
  276. #endif
  277.  
  278. }
  279.  
  280.  
  281. /* --------------------------------------------------------------------
  282.    LOCK data record
  283.  */
  284.  
  285. COUNT DLOCK(recbyt,dnum)        /* recbyt == 0  => header record */
  286. POINTER        recbyt;
  287. PFAST DATFILE  *dnum;
  288. {
  289.  
  290. /*
  291.  * the data record locks are NOT guaranteed to be deadlock free.  Therefore,
  292.  * except for the header record which is only locked by internal c-tree 
  293.  * maintenance requests, the data record lock routine returns instead of
  294.  * sleeping when a lock is denied because of a competing lock.  The application
  295.  * program must deal with the appropriate action if a lock is denied to a
  296.  * data record.
  297.  */
  298.  
  299. #ifdef FPUTFGET
  300. #ifndef PHANTOM
  301.     COUNT lokreq;
  302.  
  303.     if (!(dnum->flmode & NONEXCLUSIVE))
  304.         return(NO_ERROR);
  305.  
  306.     if (ctseek(dnum,recbyt))
  307.         return(uerr(SEEK_ERR));
  308.  
  309.     if (recbyt == DRNZERO)
  310.         lokreq = LK_LOCK; /* allow wait for lock on header only */
  311.     else
  312.         lokreq = LK_NBLCK; /* return if lock not available    */
  313.  
  314.     if (locking(dnum->fd,lokreq,1L))
  315.         return(uerr(DLOK_ERR));
  316.     else {
  317.         dnum->lokcnt++;
  318.         return(NO_ERROR);
  319.     }
  320. #else
  321.     COUNT lokreq;
  322.  
  323.     if (!(dnum->flmode & NONEXCLUSIVE))
  324.         return(NO_ERROR);
  325.  
  326.     if (recbyt == DRNZERO)
  327.         lokreq = LK_LOCK;    /* sleep if lock is not available  */
  328.     else
  329.         lokreq = LK_NBLCK;    /* return if lock is not available */
  330.     if (dnum->clstyp != VAT_CLOSE)
  331.         recbyt /= dnum->reclen;
  332.     recbyt |= ((LONG) dnum->filnum << LEFT_SHIFT);
  333.     if (ctseek(ct_key,recbyt))
  334.         return(uerr(SEEK_ERR));
  335.     if (locking(ct_key->fd,lokreq,1L))
  336.         return(uerr(DLOK_ERR));
  337.     else {
  338.         dnum->lokcnt++;
  339.         return(NO_ERROR);
  340.     }
  341. #endif
  342. #else
  343.     return(NO_ERROR);
  344. #endif
  345.  
  346. }
  347.  
  348. COUNT RLOCK(recbyt,dnum)
  349. POINTER        recbyt;
  350. PFAST DATFILE  *dnum;
  351. {
  352.     return(NO_ERROR);
  353. }
  354.  
  355. /* --------------------------------------------------------------------
  356.    UNLOCK data record
  357. */
  358.  
  359. COUNT UDLOCK(recbyt,dnum)
  360. POINTER        recbyt;
  361. PFAST DATFILE  *dnum;
  362. {
  363.  
  364. #ifdef FPUTFGET
  365.     if (!(dnum->flmode & NONEXCLUSIVE))
  366.         return(NO_ERROR);
  367.  
  368.     if (dnum->lokcnt)
  369.         dnum->lokcnt--;
  370. #ifndef PHANTOM
  371.     if (ctseek(dnum,recbyt))
  372.         return(uerr(SEEK_ERR));
  373.     if (locking(dnum->fd,LK_UNLCK,1L))
  374.         return(uerr(UDLK_ERR));
  375. #else
  376.     if (dnum->clstyp != VAT_CLOSE)
  377.         recbyt /= dnum->reclen;
  378.     recbyt |= ((LONG) dnum->filnum << LEFT_SHIFT);
  379.     if (ctseek(ct_key,recbyt))
  380.         return(uerr(SEEK_ERR));
  381.     if (locking(ct_key->fd,LK_UNLCK,1L))
  382.         return(uerr(UDLK_ERR));
  383. #endif
  384.     return(NO_ERROR);
  385.  
  386. #else
  387.     return(NO_ERROR);
  388. #endif
  389.  
  390. }
  391.  
  392. #endif
  393.  
  394. /* end of ctclib.xnv */
  395.